Blog


Meta Madness

Wanna know how I can tell that no other browser vendor participated in the creation of the new meta X-UA-Compatible tag? Because it's completely worthless - and in fact harmful - for any browser to implement!

I love this example from the overview article, including Firefox 3 as an example:

<meta http-equiv="X-UA-Compatible" content="IE=8;FF=3;OtherUA=4" />

What seems to have slipped past the Microsoft Task Force of WaSP (or maybe it didn't and they're just playing coy) is that by implementing this specific feature in any other browser immediately either: A) Reduces its market size of viable web pages that will upgrade to new versions of the browser or B) Forces new versions of the browser to bloat, including backwards support for old-style rendering.

The fundamental issue is that Safari, Firefox, and Opera will all be harmed by attempting to implement this. Anne, from Opera, completely agrees. So, with that in mind, why even the attempt at making this sound like a "generally beneficial standardization issue"? Why go through the song-and-dance? Because if it was called:

<meta http-equiv="X-IE-VERSION-FREEZE" content="IE=8" />

then developers would surely, excuse me, shit the bed in frustration over being forced to add markup just to make their web applications render in a standards compliant manner. The comments on the article definitely indicate some level of this occurring already. However, the pretense of cooperation and generally applicability needs to be dropped. It doesn't exist, it's a complete lie, and any indication of general use is a sham. Call it for what it is: A shiv for jamming standards support into future versions of Internet Explorer.

JavaScript and X-UA-Compatible

With that rant out of the way, how will this new meta tag addition effect JavaScript and DOM support in future versions of Internet Explorer? That's the weird part - no one completely knows. Let's look at some randomly-picked issues that are sure to cause a world of fun in the future.

Cross-document issues

Let's say you have a page that's in IE7 mode and an iframe pointing to a page that's in IE8 mode (or vice versa) - and now you communicate across the frames. Now let's assume, for fun, that IE8 also support JavaScript getters and setters.

var iframe = document.getElementsByTagName("iframe")[0];
iframe.contentWindow.someObj = { get value(){ return true; } };
iframe.contentWindow.someObj.value // ??
 

What happens when you bleed functionality across frames? Or even if you were to try and access functionality that doesn't exist in your engine from another? Who knows! This is positively frightening both from an implementation and user perspective.

Another random item: What happens when you use importNode across iframes that have different DOM versions?

Robert O'Callahan, Mozilla developer, has two blog posts on the subject that are both quite good.

Script Versioning

Up until this point, if we wanted to pick a different version of JavaScript to use we would do something like the following:

<script type="application/javascript;version=1.8">...</script>

This works well in browsers that support it. However, with this new meta tag addition, Internet Explorer is pegging JavaScript versions to versions of their rendering engine. This means that (theoretically) if you wanted JavaScript 1.5 support you'd have to, also, be content with bad CSS support. If you wanted to upgrade to a new version of the scripting engine you'd also have to upgrade your CSS and markup as well. This is completely throwing out any sort of versioning system that already exists for JavaScript and forces users to use this new, inferior, system instead. How completely frustrating.

What I also find interesting is that, previously, Chris Wilson was concerned about implementing multiple versions of a JavaScript engine in order to maintain backwards compatibility. What they're doing now is, effectively, forcing themselves to have multiple JavaScript engines. So either they're gearing up to support JavaScript 2 or they've just lost one of their major qualms with the upcoming specification.

Minor Versions and Security Fixes

A final point that doesn't seem to be accounted for, at all, is the inclusion (or exclusion) of minor browser versions (including things like security patches). Internet Explorer hot patches have been known to cause problems in the past with web page functionality and rendering. However, since there's no way to specify which patches you "like" in this new meta tag scheme you're forced to consume them all.

The end result will be one in which: A) You're either constantly dodging mistaken bullets from the Internet Explorer team as the push out new releases or B) They're not going to do as many, if any at all, updates to the browser out of fear of breaking backwards compatibility. Honestly, I assume that B is far more likely, therefore you can be excited about looking forward to future, static, bug-laden releases of IE in the years to come!

On a whole, I really wish that this process had been done more in the open than it was. I doubt that as many issues, that we're seeing now, would've arrived. I absolutely don't envy Internet Explorer's situation in the matter so, for the sake of the web, let's hope they come up with an acceptable solution.

Tags: javascript, browsers, rendering

Sub-Pixel Problems in CSS

Something that jumped at me, recently, was a rendering dilemma that browsers have to encounter, and gracefully handle, on a day-by-day basis with little, to no, standardization.

Take the following page for example. You have 4 floated divs, each with a width of 25%, contained within a parent div of width 50px. Here's the question: How wide are each of the divs?

The problem lies in the fact that each div should be, approximately, 12.5px wide and since technology isn't at a level where we can start rendering at the sub-pixel level we tend to have to round off the number. The problem then becomes: Which way do you round the number? Up, down, or a mixture of the two? I think the results will surprise you, as they did me.

Opera 9
Safari 3
IE 6
IE 7
Firefox 3
Firefox 2

We have three completely different camps here:

  • Round the numbers down - Both Opera and Safari round down the widths of all the divs to 12px. This leaves a 2px gap (note the green) to the right of all the divs. If you've ever wondered why your nicely-aligned navigation doesn't fill up the full contents of a container in these browsers, now you know why. On the plus side, at least you know what the width of these containers will all be the same, no matter what.
  • Round the numbers up - Both Internet Explorer 6 and 7 round the widths of all the divs up to 13px. Doing this causes the floated divs to immediately wrap, breaking layouts. This is obviously wrong as it causes many safely-numbered layouts to break for no obvious reason.
  • Round some numbers up and some down - Both Firefox 2 and 3 mix the rounding of the div widths to 12px and 13px. The mix of rounding is done as to provide an even result at the end (making it flush with the far edge). The obvious side effect is that the divs no longer have a consistent width to them (even though an equal width was specified by the CSS). Additionally, the reported (via a JavaScript computed style call, like offsetWidth) width of the element remains at its reported 12.5px not providing the user with any indication of which way the rounding is occurring. And to add another confusing wrench in the works: The order of which divs have a width of 13px or 12px has been flip-flopped in Firefox 3. This was done to improve efficiency and speed and seemingly little, to no, effect on general web site rendering.

I was talking this over with some Mozilla developers and David Baron explained the situation quite well:

We're trying to meet a bunch of constraints that can't all be satisfied at the same time (the proof is left as an exercise to the reader, though I may have actually written it out once in a Bugzilla comment):

1. 4 adjacent objects of width/height 25% (for example) starting at one edge of a container should end exactly at the other edge; there should never be an extra pixel in the container and they should never be wrapped due to being a pixel to wide

2. objects that are logically adjacent should always touch visually; there should never be a pixel gap or a pixel of overlap due to rounding error

3. objects given the same width should occupy the same number of pixels

4. object boundaries should always (visually) be aliased to a specific pixel boundary in the display (they should never be blurred)

The one [Mozilla] sacrifices is typically (3), except for borders where we sacrifice (1) by rounding the widths to pixel boundaries much earlier.

The especially strange part, in all of this, is that there's really no right, or wrong, here. How this behavior is supposed to play out by the rendering engine isn't dictated by the CSS specification, having it be left up to the implementation to render as it sees fit. Obviously the four guidelines outlined by David, above, could serve browsers well but they are forced to sacrifice at least one of them in order to meet most of them.

The whole situation is quite fuzzy and frustrating - I'm not sure what the best action is, moving forward, but at the very least it's in the open now where we can think about it some more.

Tags: rendering, browsers, css

Current Projects

jQuery JavaScript Library

jQuery

Comprehensive DOM, Event, Animation, and Ajax JavaScript Library.

Recent Projects

Pro JavaScript Techniques

JavaScript Book

The best techniques for professional JavaScript. Published by Apress.


Hosting provided by the cool dudes at Engine Yard.