Four browser notes

In case you’re wondering why this blog is updated so rarely; I’m taking a slight break from web development, and I’m working on a major upgrade of my Dutch politics section. It’s not ready yet; I’ll let you know when it is.

However, while working on it I found a few browser peculiarities, and I thought I'd let you know. There’s one IE bug; one case in which IE does the right thing and the other browsers don’t; the third is a Chrome peculiarity (not a bug); the fourth is an undocumented property in Opera.

Opacity in IE8-as-IE7

First of all, I found a difference in opacity handling between IE8 in IE7 compatibility mode and a true IE7.

In IE7 (both pure and IE8-as-IE7), opacity is set as follows

.opaque {
	filter: alpha(opacity=50);
}

In IE8, on the other hand, opacity is set as follows (and as far as I understand this is a temporary solution on the way to proper opacity support):

.opaque {
	-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
}

I needed opacity for some of the nice political maps I’m preparing, and did the following:

.opaque {
	filter: alpha(opacity=50);
	-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
}

Works fine in IE8, and in IE7. But not in IE8-as-IE7.

It turns out that you have to swap the lines; apparently IE8-as-IE7 gets confused when the -ms-filter follows the filter.

.opaque {
	-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; // first!
	filter: alpha(opacity=50);					// second!
}

That’s one more bug solved (and I notified the IE team), but it set me thinking. Do we have to pay any attention to IE8-as-IE7?

Test in IE8-as-IE7?

This is probably as good a place as any to remind everybody how IE8-as-IE7 works.

  1. By default, IE8 renders pages with the IE8 rendering engine. (We had a frightful argument about this at the start of the year.)
  2. However, the website author can order IE8 to use the IE7 rendering engine instead by adding a <meta> switch to all pages, or to the HTTP headers:
    <meta http-equiv="X-UA-Compatible" content="IE=7" />
    
  3. Furthermore, IE8 allows the user to switch to the IE7 rendering engine by pushing a button next to the location bar. (Note that this button is only present if the current site has no <meta> switch. If it does, the switch is obeyed and the user cannot select another rendering engine.)
  4. Fortunately, IE remembers what rendering engine you use for a certain site. If you decide to use IE7 compatibility mode to view QuirksMode.org, that mode is used every time you return to it. If you surf to another site without a <meta> switch, IE8 initially returns to IE8 mode, although you can still overrule that by pressing the button again.

In the absence of a <meta> switch IE allows you to select a rendering engine on a per-domain basis. This is good to know (I didn’t test this before).

So when it comes to your visitors you can ignore IE8-as-IE7; they will always see your site in IE8 mode initially, and if there’s no reason to switch they won’t press the button and remain in IE8 mode forever. (At least, that’s what I think will happen. We’ll have to see how users react to the presence of the button.)

However, IE8-as-IE7 is also useful to web developers. Eventually, you won’t have to install any IE version except for the latest. It will contain all previous versions (except IE6) in compatibility mode, and testing your website in such a mode becomes a simple matter of temporarily adding a <meta> switch.

Add switch, test site, make changes, remove switch (or switch to yet another compatibility mode). Cool.

But for this scenario to work properly, IE8-as-IE7 (and future IE9-as-IE7 etc.) will have to emulate a “pure” IE7 perfectly. With the opacity bug, that’s not quite the case, and that’s why it’s so important to test IE8-as-IE7 for bugs.

So I’d like to suggest testing your sites in IE8-as-IE7 for the moment, and comparing them to a pure IE7. Any bug you find will help the IE team. It’s certainly what I’m going to do in the next few months.

HTML: IE gets it right

While working on the same site, I found a curious difference between IE and all other browsers, and contrary to the usual state of affairs IE gets it right, and all other browsers get it wrong.

In my politics site I want to be able to embed nice graphs and maps in the main text wherever I want. So I devised a system of tags:

<include type="parliament" year="1967" />

This embeds a graph of the 1967 Dutch parliament in the text, at the indicated spot. I wrote the script, tested in in all browsers, and it works. Cool.

However, I ran into serious trouble when I wanted to do some cleaning-up of the DOM structures. I intended this <include /> tag as a kind of data-island; a construct that is either interpreted by the script or ignored completely but doesn’t influence the rest of the page and forms a separate DOM element.

Unfortunately, all browsers interpreted it as an opening tag, and placed all subsequent content within that tag. In the snippet below, I intended the two paragraphs and the <include /> to be children of the same parent node.

<p>Yaddah yadday yah. Yaddah yadday yah. Yaddah yadday yah. Yaddah yadday yah.</p>

<include type="parliament" year="1967" />

<p>Yaddah yadday yah. Yaddah yadday yah. Yaddah yadday yah. Yaddah yadday yah.</p>

Instead, what browsers did was make the second paragraph a child of the <include />.

Except for IE. Only IE obeyed the closing slash and did what I originally intended; only IE made the <include /> a sibling of both paragraphs.

Right now I’m in bitching phase; I’ll probably cave in and add </include> tags later on. But how I wish the other browsers understood the closing slash. (And I am using an XHTML doctype, so they’re supposed to know what a closing slash means.)

Appending to a paragraph

On a related note, I once made an HTML error that led to frightful errors in IE; and again it turned out that IE is right and the other browsers are wrong in not showing the error.

<p>Yaddah yadday yah. Yaddah yadday yah. Yaddah yadday yah. Yaddah yadday yah.<p>

<include type="parliament" year="1967" />

Note that I accidentally forgot the slash in the closing </p>. This error made the <include /> a child of an otherwise empty <p>.

IE threw an Unknown Runtime Error; the other browsers executed the script correctly. After thinking about it, I decided IE was right and the other browsers were wrong.

Each of the graphs JavaScript produces has a container <div> as topmost element. This <div> is inserted into the page just before the <include />, and the script appends the actual graph to it. In this particular case, they append a <div> to a <p>

The point is, a <p> element is the lowest block-level element there is. It cannot contain other block level elements; only inline ones.

IE obeys that rule. It refuses to append a <div> to a <p>, because that’s not allowed. All other browsers ignore the rule and append the <div>. They’re wrong.

Chrome: looping through object members

Take a JavaScript object and loop through it:

var myObject = {
	"member1": "yaddah",
	"member2": function () {
		return "yaddah"
	},
	"member3": ["yaddah","more yaddah"]
}

for (var i in myObject) {
	alert(i);
}

All browsers will alert "member1", "member2" and "member3", in that order. They follow the source code order of the members.

Chrome doesn’t. It will loop through the object members in what appears to be a random order.

Now this is not a bug. Every JavaScript book (including my own) states that JavaScript interpreters may loop through the members of an object in any order they want.

Parts of my script relied on the browsers looping through object members in source code order. While writing them I knew I was doing the wrong thing, but I thought “Ah well, all browsers do what I want anyway.” Not so. I have to add an array that contains the member order.

This is one of the most tricky areas of browser compatibility. What counts for more, the formal specification or the practical implementation by all browsers?

If the change is relatively easy to implement, I would suggest the Chrome team follow the lead of the other browsers and loop through object members in source code order. I can’t force them spec-in-hand, though; the specification clearly gives them the option to retain the current behaviour.

Opera: the text property

Finally, Opera turns out to have a text property for all DOM nodes (or at the very least for all <div>s). This throws my graph creation script off, because it sometimes stores information in the text property. Opera shows that information on screen. All other browsers properly hide it until the right time has come.

The solution is simple: use a different name for my property. Nonetheless, I wish Opera had documented this proprietary feature.

This is the blog of Peter-Paul Koch, web developer, consultant, and trainer. You can also follow him on Twitter or Mastodon.
Atom RSS

If you like this blog, why not donate a little bit of money to help me pay my bills?

Categories:

Comments

Comments are closed.

1 Posted by Robbert Broersma on 27 November 2008 | Permalink

The property order bug has been explained on the IEBlog several months ago:

http://blogs.msdn.com/ie/archive/2008/09/08/microsoft-css-vendor-extensions.aspx

2 Posted by Robbert Broersma on 27 November 2008 | Permalink

The text property on HTML nodes actually is a Microsoft extension to the DOM. Of course, the text attribute is also specified in the DOM Level 2 HTML spec a couple of times (for the title, script, body and option elements), but I don't think the property is based on that spec.

http://msdn.microsoft.com/en-us/library/ms761386(VS.85).aspx

3 Posted by Rijk on 27 November 2008 | Permalink

About 'include \': unless you are actually sending with an XML mime type, browsers like Opera will handle your document as HTML, not XML, with all the error correction needed for HTML regardless of the doctype you stick on top of the tagsoup. This includes ignoring the / included in empty tags like BR and IMG and LINK. It doesn't surprise me the same thing happens when you invent your own element: there is no way to communicate to the browser (when using HTML) that you think of it as an empty element.

4 Posted by Rimantas on 27 November 2008 | Permalink

Just to second what Rijik said: it is about content-type, not doctype.

5 Posted by Paul D. Waite on 27 November 2008 | Permalink

> ...but it set me thinking. Do we have to pay any attention to IE8-as-IE7?

Did anyone else imagine the question appearing in close-up on an old PowerBook screen, with a voice-over by Sarah Jessica Parker?

Just me?

Fair enough.

6 Posted by Krijn Hoetmer on 27 November 2008 | Permalink

Anne already told us that doctype thingy 4 years ago: http://annevankesteren.nl/2004/07/mime

7 Posted by Thomas Broyer on 27 November 2008 | Permalink

Let me add another point about your 'include' experience: IE gets it wrong, it pays no attention to your "/" (if you go explore the DOM, you'll even find an attribute name "/" with value "" on your include element!).

Now, try using an end tag, and IE will put an element in the DOM named "/include" right where you put your end tag. You'll then have an "include" empty element and a sibling "/include" empty element.

You can read about it all at http://intertwingly.net/blog/2007/05/04/Inline-SVG-in-MSIE (a year and a half ago) and the (now well-known) workaround is to document.createElement("include") somewhere before IE actually sees the 'include' element (it will thus recognize it and parse its content as child elements and the end tag as closing the element).

Note that most if not all browsers will create the "/" attribute! (and HTML5 parsing algorithm dictates to do so)

8 Posted by Robbert Broersma on 27 November 2008 | Permalink

More on the createElement hack:

http://xopus.com/devblog/2008/style-unknown-elements.html

9 Posted by Tino Zijdel on 27 November 2008 | Permalink

I think IE is wrong in throwing an error when trying to append a DIV to a P element (if that's what really is the reason for the error; I can't reproduce it in IE7); the DOM doesn't care about HTML parsing rules, nor should it. If you think that behaviour is appropriate than it should also throw you an error for each undefined attribute and each undefined element (such as your INCLUDE element - especially when you try to wrap that element inside a P - how is the browser to know if that is intended to be inline or block? Most browsers do assume the latter btw).

I think it is very contradictory if you on the one hand expect browsers to throw errors for wrong nesting of elements, but on the other hand expect browsers to support fictionary elements in a way that suits you best. And why would you use fictionary elements? Imo using DIV or SPAN and using special classes suits the purpose just fine.

As for the error: have you also tried appending f.i. a DIV to an inline element? Imo that should than also throw an error.

10 Posted by Tino Zijdel on 27 November 2008 | Permalink

continued:

Posters above me have already explained that XML syntax doesn't work in HTML parsing mode, and that parsing mode is determined by mimetype, not doctype, so no need to point that out any further, maybe except for the reminder that IE8 still won't support XHTML.

Now for the other points: having to use -ms-filter with it's overly verbose syntax for alpha-transparency in IE8 is just plain silly; why can't they just support opacity or -ms-opacity? That besides the ordering-bug which is a non-issue if you use seperate stylesheets for different versions of IE.

As for the order-issue wrt object properties; I remember Opera used to have the same issue. I agree that it would be helpfull if that would keep assignment order in iterations. Let's hope Chrome will fix that. Meanwhile when order is important I tend to just use an array of objects.

11 Posted by David Håsäther on 27 November 2008 | Permalink

The Chrome issue is reported here: http://code.google.com/p/chromium/issues/detail?id=883

12 Posted by ppk on 28 November 2008 | Permalink

@robbert: I use my custom text property on a div, and only Opera displays the funky behaviour. I'll look into the DOM-defined text property; if it's widely spread it belongs in the Tables.

As to the mime type thing; frankly I had forgotten its existence. I never liked it, partly because in the past it was an ideological talking point for web standards fascists.

Now that I reconsider it, I suddenly understand why I don't like it. The mime type system of switching to XML means that there is *no client side way* to make that switch; it all depends on the server. We've got countless switches nowadays, but the mime type switch is the only one you can't set with some declarative HTML. As far as I'm concerned that is a mistake.

I knew about the createElement hack, but thought it had nothing to do with the current situation. But Thomas Broyer may very well be right.

As to support of custom elements; all browsers do, so why not use them? The reason I used them instead of a div or span was to be able to loop only through the include elements and not having to go through all divs to see if they might contain include instructions.

And yes, I missed the IE blog post that explained the bug.

13 Posted by Tino Zijdel on 28 November 2008 | Permalink

> but the mime type switch is the only one you can't set with some declarative HTML.

Sure there is: META, but Content-Type in META is generally ignored afaik except for charset.

Having such switch in markup doesn't really make sense; it means that the browser will have to switch renderingmode during parsing. And then there is still IE that just doesn't support XHTML, so it's useless in the real world anyway.

14 Posted by Janie Parrish on 29 November 2008 | Permalink

I love the new Google Chrome! Good luck on finishing your politics!

15 Posted by Brad Neuberg on 29 November 2008 | Permalink

I ran into the issue around empty tags that you found for the SVG shim I'm creating. IE allows me to have empty elements such as (though I use IE Behaviors rather than the createElement trick so that the node is a real member of the DOM, with CSS, children if needed, etc.). I couldn't for the life of me though get Firefox or Safari to work with empty elements. I'd love to find a trick for that scenario. Has anyone ever been able to get empty elements in normal HTML (not XHTML or XML) working in Firefox or Safari? If I could just get a representation of the page _before_ it is parsed into the DOM that would be a workaround, but there doesn't seem to be a way to do that without refecthing the page in the background using XHR, which is unacceptable.

Best,
Brad Neuberg

16 Posted by jennhi on 30 November 2008 | Permalink

At the risk of derailing the intended subject of the article, I need to ask: can you please explain the "include" script? If it's on another article on your site, I can't find it.

17 Posted by ppk on 5 December 2008 | Permalink

The IE team has notified me they have fixed the filter issue. So the next IE8 release will not suffer from this particular bug again.

Cool!

18 Posted by Kangarado on 6 December 2008 | Permalink

Apart coding, nobody mentioned the pretty visual effect or the change implemented in Chrome ... I like that the 'page title' in the blue bar on top isn't showing there in Chrome browser, which I'm using now to post this comment.

19 Posted by Br4m Hogendaal on 23 December 2008 | Permalink

@ ppk: When will the new IE8 be released?
Chrome has gotten out of beta a few weeks ago.