I wrote a blog post last week where I discussed some of the good lessons from the success of Firefox. I truly believe Firefox is a great browser, and I am glad that competition has forced Microsoft to pull its IE developers out of suspended animation to update its ability to handle CSS properly. Let's just hope there are no H.R. Giger-inspired aliens on board.
Well, I'm proud to say I've done that, and the service on which I have been busily working for the past several weeks renders properly in all of them.
I can't say, however, that it wasn't without work, work which I wouldn't have to worry about if one browser reigned triumphant. One triumphant browser, however, means the browser doesn't get updated very often. So, thank goodness for competition.
Even so, I did run into some rather unusual problems. And, as it turned out, the problem wasn't with IE. Rather, it was with Firefox, Safari and Opera.
Some of the pages on the site I am updating were written awhile ago, and used tables for layout. For one of the new screens, however, I decided to write it from scratch to do things the modern "CSS" way. For reasons that Talkback participants have explained to me but I have not yet completely accepted (I think it makes sense to have proper GRID-style layout primitives, and TABLE is used an awful lot that way), that means TABLE tags are out, and DIV tags are in.
The page, in this case, was a page for contact information. Each row had a label, followed to the right by a set of fields related to the labeled functionality. One of the advantages of TABLE tags as a layout primitive is that it spontaneously sizes itself to the content, making it easy to add new rows later. I wanted to maintain that behavior in my DIV-oriented layout, so that I could add new rows and fields with impunity without having to go through and manually recalculate a bunch of fixed-position rows.
To effect this, I created a CSS class called rowAttributes that defined the row as "position: relative" (which is important, as CSS will treat it as the baseline against which all contained positioned divs are interpreted). I then created a class called labelAttributes, which had an absolute position and a fixed width. Last, I created a class called editFieldAttributes, told it to "float: right," and gave it a fixed width. This isn't ideal, as I would really rather make the editFieldAttributes position: absolute (relative to the containing row DIV). That, however, causes it to break on all browsers, which is somewhat understandable; absolute positioned divs have no "natural" height to speak of unless you give it one.
You can see a demonstration of the code here (which is, in its essentials, the same as what I am using on my site). The border I have displayed around each row is just there as a sanity check, and shows that the contained divs live properly inside the parent row div. If you run this page in IE, it works, and the border indicates the row properly contains its children. If you run it in Firefox, Safari, or Opera, it doesn't. In Firefox, Safari and Opera, the label block clearly refuses to live inside its containing row (and all the row border "rubber bands" are clustered together at the top of the block containing the edit fields).
Now, someone is sure to point out that if Firefox, Safari and Opera all consistently fail to render the HTML and CSS, then it is IE that is rendering it "wrong." Well, that's like saying that because a room full of teenagers can't find Iraq on a map, that Iraq does not exist. I'd accept that IE was being overly forgiving if I was doing something illogical, e.g. that I wasn't putting my labels inside a containing row DIV, or that I tried to allow my absolutely positioned DIVs to have a "natural" height based on the layout of their contents. I'm not doing any of those things.
I've tried multiple variants of this code (this one just struck me as the "cleanest"), and all of them worked in IE, while none of them worked in Firefox, Safari or Opera. This is why, as a fallback, I chose just to use absolute positioning for each row. That doesn't make me happy, but it works consistently across browsers, even if the "rubber band" border shows that the browser is really confused about what the "row" actually contains. That second version (with absolute positioned rows) is the second edit field block in my bit of demo code.
IE started to grate on me when I began to appreciate the power of CSS, and wished IE did a better job of supporting it. IE 7.0, however, does a good job of supporting CSS, at least the bits that I care about. Now I'm back to frustration at the inconsistency across browsers.
By the way, I found healthy numbers of places where rendering was inconsistent between Firefox and Safari or Opera (Safari and Opera seem to be in lockstep from a rendering standpoint). One that springs to mind is its treatment of non-existent style sheets. I had a style sheet that was supposed to only be downloaded for the Chinese version of our old site. To effect this, I just detected the culture within which the page was running, and created a request for a style sheet that was the two-letter language code followed by the .css suffix (for chinese, this was zh.css). For most languages, this file did not exist, which didn't affect rendering in IE or Firefox one bit.
I'm not saying this is "ideal" code. More efficient code would have been to have some master list of languages that required custom CSS attributes, and only generate the proper CSS-related STYLE tags when the language was one that required it.
In Safari and Opera, however, it interpreted the HTML retrieved for a 404 error code (the code returned when it can't find a CSS file) as CSS, which can lead to random results. In the case of our pages, it made all the links and buttons (which were actually modified links) look red. It took a bit of research to figure that one out, but it is now resolved.
What's the takeaway from all this? Open standards are good and important. However, until every browser somehow manages to interpret a massive and complicated standard specification in the exact same way, there is no such thing as perfect consistency. Standards help to make the likelihood higher, but they are no assurance. There is still going to be strong incentives to pick one browsers as "dominant."
It's also worth pointing out where IE is getting it right.
UPDATE: Talkback participant andrewjg figured out the perfect solution, and it is dazzling in its simplicity; simply add "clear: both" to the rowAttributes class, and everything magically falls into place (though the "rubber band" border still doesn't wrap the contents, but that doesn't matter; I'm not using that on my site, and only added it to help make clear the problem I was trying to describe).
I really do want to do things the CSS way, which is why I went through the trouble of making my new page use DIVs for layout. This could make it possible. I haven't updated my site yet, but this looks promising.