Some problems with CSS implementations, and a workaround

Note: this document contains a few worthwhile observations together with some out-of-date suggestions (it's not been revised significantly since late 1997). Pending a thorough revision, take it with a grain of salt. For the latest on dodging CSS bugs, see The Verso StyleServer.

This page documents a few serious discrepancies between implementations of Cascading Style Sheets (CSS) in Netscape 4.0 (Mac and Windows) and Internet Explorer versions 3.0.x and 4.0b1. It assumes you understand a good deal about CSS already, but may not yet have attempted to make it work across implementations (including operating systems). It also suggests a workaround strategy (complete with sample code), which may regrettably be necessary in order to use CSS in more than a trivial way on the open Web.

Perhaps the most common "hacks" practiced in HTML on the Web aim to gain control of whitespace, especially vertical whitespace (inter-element spacing, leading, etc.). The HTML header and paragraph elements have been replaced among visually-oriented web authors with combinations of <font> tags, line breaks, spacer GIFs, and non-breaking space characters. There is also a strong tendency to make images of text, for the sake of assuring a special typographical character. These are essentially unfortunate ideas - a point I will not argue here. CSS should make it possible to abandon these hacks and use standard HTML. Unfortunately, CSS implementations make this difficult.

Getting on with it

Here's a rendering I attempted to achieve with standard markup and CSS for a particular window size (just layout - ignore color. Assumes you've got the free cross-platform font Verdana installed.) Note that the space between paragraphs equals that between lines. Note also the character of the font Verdana at this particular size (rendered on a Macintosh at 11 points/pixels).

Here is the live HTML/CSS of my best attempt to realize this rendering in Netscape 4.01(Win32). Please see the source of the referenced document to see what's going on. This was ultimately a failed experiment, so I have left things messy for your analytical enjoyment.

Renderings of the above in the four major "CSS-enabled" browsers.

Win Netscape 4.0 final - close but no cigar. Neither the "points" nor "pixels" sections match the rasterization of Verdana in the ideal rendering, nor is the inter-paragraph spacing right. The closer I came, the more I messed it up for the other browsers:

Win IE4b1 - The rasterization of Verdana's spot-on (at least in the "points" section, but the inter-paragraph spacing has gone to hell. If I amend to fix here, it breaks in the other guys.

Mac Netscape 4.0b5 - A train wreck in the "points" section. CSS authors: please realize that "points" are not a reliable cross-platform unit. Spacing's a bit off even in the "pixels" section from the Windows rendering. You'd think a pixel would be a pretty unambiguous unit, huh? Pixels have their own problems: resolution-dependency. What's necessary is for designers to be able to specify the pixel-density of their displays, and to let UAs/OS's scale as necessary. Bottom line: if it is not possible for CSS to specify consistent renderings of the same font data across platforms and applications, designers will use more and more images of text as the Web heats up as an "identity" vehicle.

What's going on

If you specify zero (vertical) margin on consecutive elements, IE takes the line-height specified on the contiguous elements as the actual margin. Netscape, in contrast, discards the line height for the first line and sets the margin to zero. I believe IE's interpretation is correct, but Netscape has shipped across platforms already, notably on the Mac, where most presentation- sensitive web work is prepared. This document shows an attempt to cater to Netscape's interpretation, and reveals many annoying discrepancies between typographical and linear measures, especially across platforms.

There are many more grave discrepancies than shown here - if it wasn't so sad, it would be funny. By rushing out such dangerously substandard CSS implementations, the browser vendors threaten to negate even their future, more conscientious CSS implementation work. A remedy is to use scripting languages to serve separate stylesheets to different implementations. This is unfortunate because it might let browser vendors shuffle their responsibility onto web authors indefinitely, because fixing the bugs will break the workarounds. I think that's better than the alternative of letting CSS rot in developers' perception as a hopeless mess, however. A better use than hacking around bugs is simply to withhold CSS from dangerously substandard implementations, effectively permitting their "boycott," all without penalizing users by withholding content.

By all means, report all CSS bugs you find to their owners, via their bug-reporting pages (Netscape, Microsoft). Of course they've heard it before, but it must help prioritize things if they hear whole choirs of complaint.

Usage notes

If you use this, please do think about forward compatibility issues and new entrants to the browser market. What happens when Netscape 4.x is released, that may fix some bugs but introduce others? This is not maintenance-free code. I recommend making "default.css" first, according to the spec (not hacked to work around implementation shortcomings). Then modify as necessary for the best implementation available on your platform. Then others as time and resources allow.

The code above serves no stylesheet at all to IE3, unless the user has disabled scripting but not style sheets. You might encourage IE3 users to upgrade to 4 as soon as it is released, perhaps in a CSS-hidden note.

Of course, this sort of thing could be implemented server-side as a CGI script, too. Want to submit sample code?

A few months after writing the above, a new, simpler strategy comes to mind: write complete stylesheets using the spec and best available implementation as guides. Before linking documents, separate out the (small) set of "safe" features into a primary stylesheet. Reference the remaining "unsafe" set from the primary via @import. IE4's the only significant browser I know that will get the secondary sheet. If necessary, include IE4 "crutch" code in the secondary via XSSI. If enough people do this, perhaps it will serve as a discouragement to vendors to release more flaky implementations.