Working together for standards The Web Standards Project

Pandora’s Box (Model) of CSS Hacks And Other Good Intentions

By Tantek Çelik | November 27th, 2005 | Filed in Browsers, Bugs, CSS, Education, HTML/XHTML, Microsoft, Outreach, Validation, W3C/Standards Documentation, Web Standards (general)

This Thanksgiving I’ve decided it’s about time that I provided some more background and analysis on one of the things I am certainly unintentionally (in)famous for.

Skip to comment form

This Thanksgiving I’ve decided it’s about time that I provided some more background and analysis on one of the things I am certainly unintentionally (in)famous for. This entry was started at 7pm on Thanksgiving evening, but took me until now to complete.

Before CSS hacks

I don’t know who first came up with using the presence of a ‘media‘ attribute on <link> or <style> to hide CSS from Netscape 4, but it was the first technique that I remember hearing of to use a perfectly reasonable HTML feature (yes, the ‘media’ attribute is in HTML, not CSS) to deliver CSS selectively to browsers that supported a certain feature.
This HTML-based “filter” was perhaps the first such technique, though it would be many years before the term “filter” was introduced as a general term for such techniques.

Banishing version four browsers

The first filter I came up with (again, before they were named as such) was perhaps the @import with quotes filter, which I didn’t even bother writing a page about in particular because it seemed so simple: @import “foo.css”; is only supported by IE5, NS6, Opera3 and better. I just posted an example usage at the time for Web Standards Project‘s Browser Upgrade Campaign (BUC). That particular legacy contribution was also made anonymously to one of the ALA redesigns, though I believe Jeffrey has outed me at some point since.

Neither the HTML ‘media’ attrribute filter nor the CSS @import quotes filter, in my humble opinion, qualified as hacks, because they lacked what some might term the essence of a :
either a kludge, or the opposite of a kludge, as in a clever or elegant solution to a difficult problem. Neither of those filters were particularly kludgy (warning, not a Scrabble word), nor clever. In other words they were too “obvious” to really be considered hacks.

Seemed harmless

Anyway, the @import filter seemed harmless enough. At the time the only big difference it made was to filter out IE4.x (both Mac and Windows), which had already been obsoleted by IE5 (both versions). And it was praised as: … for people who make websites, that is nothing short of revolutionary.
Sidenote: note the fact that that article on ditching <table>s for layout is almost FIVE years old
yet those of us that are real professionals still have to repeat the message .

Thus the idea of using a feature of CSS to essentially do a lightweight form of browser specific style sheet switching was born, but the ‘s () of had yet to be opened. That would come exactly one week later.

Hacking open the and releasing the filters

Jeffrey Zeldman expressed to me how nice it was that it was possible to write CSS without having to worry about what might look bad in
(or even crash) obsolete browsers like Netscape 4. Having been freed to use more of (and depend more on) CSS, he and many others following ‘s suggestions quickly ran into the next issue which was the inconsistent box model treatment between IE5.x/Windows and /Windows.

If only there were a way to send one width to IE5.x/Windows, and another width to modern browsers which supported the CSS box model… is a rough approximation of what said (emailed) to me at the time.

Eager to be helpful, and armed with the intuitive knowledge that the key to Pandora’s Box of could be hidden amongst the jungle of CSS1 section 7.1 parsing tests, I went hunting. It didn’t take long until (with Todd Fahrner’s help) I discovered how test twentyb (rotation-code: "\"}\""; – look familiar?) messed up all versions of IE5.x/Windows,
but no other modern browser. After that it was a simple manner of finding an abandoned CSS2 property which accepted arbitrary string values.

I had opened Pandora’s Box (Model) of CSS Hacks, and there was no turning back.

Shortly thereafter, I generalized the Box Model Hack to enable hiding entire style sheets from IE5.x/Windows and CSS Filters were born. More followed soon thereafter.

Intelligently designed hacks

Implicit in the story above are a set of design which I kept in mind when I first set about creating CSS hacks, and which I really should have noted at the time. Given all the hand-wringing about CSS hacks incited by my colleague Markus Mielke, it’s about time I documented these principles. More on the hang-wringing later.

A should (or MUST in the RFC2119 sense if you prefer):

  1. Be valid. Invalid hacks are unacceptable. Back in the heyday of Web 1.0 (i.e. the late 1990s), the The Web Standards Project and numerous others were already spreading the message of better coding through validity, and thus hacks themselves had to validate as well. (Nevermind that many/most so-called “Web 2.0″ sites can’t be bothered to validate. See above about the real professionals having to repeat the message).
  2. Target ONLY older/frozen/abandoned versions of user
    agents / browsers. When the Box Model Hack was introduced, we were already playing with betas of IE6/Windows (back when we expected there would be an IE6/Mac), and so we knew how to make sure it wasn’t affected. And now we’re playing with betas of .
  3. Be ugly. It’s actually a good thing that a hack be visually ugly from a coding aesthetic point of view in the hopes that the
    ugliness will be a reminder that the hack is a hack, and should incite a tendency for people to a) minimize it’s usage, and b) remove it’s usage over time. At it’s core, browser switching is one of those things you really shouldn’t, but must, do to get your job done. Hacks’ ugliness are like the equivalent of persistent warning tags, a reminder to dispose of them when no longer necessary.

Explosion of CSS hacks and filters

But I didn’t document those principles at the time. Once said Pandora’s Box was opened, it didn’t take long for the notion that hacking CSS was a “good idea” to spread far and wide in the web design and development community (much further than I could have possibly expected, to the #4 result for ‘hack’ on Google, and even onto t-shirts!). Of course once hacks for IE5.x/Windows had been discovered, and refined into the concept of “filtering” which browsers got to see whole style sheets, it was only a matter of time before hacks were developed and documented for nearly every browser. Nevermind that so many of the hacks violated the above-mentioned principles. Those ideas spread and mutated without any such strings attached.

At this point I can only strongly recommend that people evaluate these myriad hacks based on the above principles before using them.

IE7 Team Puts CSS Hacks On Notice

Now, about that inciting and hand-wringing that took place last month.

The irony is that I don’t disagree with the details of Marcus’s MSDN post. Note that his “Call to action: Please check your pages” does not mention a single one of the CSS hacks I developed. The one partial overlap is the use of the child “>” selector, which was introduced as part of the Box Model Hack to “Be Nice To Opera” (Opera 5 in particular, which at this point is probably ignorable – anyone even hear of anyone that still uses Opera 5, even for testing purposes?).

The sad thing is that most of the hand-wringing could have been avoided (as noted in the comments) if people would first try fully standards based cross-browser solutions before resorting to hacks.

However, the undertone of that blog post (and what Markus and Chris Wilson have expressed to me and others in person) is that web developers must stop using CSS hacks altogether.

I know that’s perhaps a bit of a hyperbole, but that’s the message that’s been heard nonetheless. However, such a message is, with all due respect, the impractical perspective of folks who are not a professional web designers / developers. I know this, I was there once too.

Avoid Targeting Current Versions Of Browsers

To be specific, the problems with hacks have arisen because of hacks that are targeted at a current browser, namely, IE6/Windows. E.g.

* html

Using A CSS2 Feature Is NOT a Hack

And a misperception that the use of an implemented feature is a hack.

E.g. people (ahem, starting with the “BMH” as noted) have used the child selector to send “valid CSS” to “compliant implementations”, e.g. with


That’s not a hack. It’s not targeting a specific browser. It’s actually
inclusive of all browsers who would support CSS2(.1) selectors.

Sending valid CSS to compliant implementations is proper behavior.

400 Tiny Violins For the Newcomer

(With apologies to Star Trek)

Does this make it harder for new/late implementations (like IE7) to come along and support that selector?

Why yes it does. This is no surprise.

If you support the child selector, now all of a sudden you have to
compliantly support all the other properties/values of CSS2(.1) that authors have been successfully using with the child selector.

But given that several other browsers do so (otherwise authors wouldn’t be using the child selector), and thus the market has demonstrated this is not a problem, this is a reasonable expectation.

However, if a browser is somehow unable to do so, then the answer is simple.

Don’t implement that selector, until that browser is able to do so. IE5/Mac did so, so can IE7, more than five years later…

This may seem “unfair” that that these features (a CSS2(.1) selector and
some CSS2(.1) properties/values) are now “tied” together in terms of
requiring implementation support, but guess what?

CSS2(.1) doesn’t say you can implement part of the spec. You’re supposed to implement the whole spec in the first place.

The Red Queen Problem

Obviously this was hard (in fact, impossible for self-contradicting and ambiguously written REC-CSS2 in 1998), and browser vendors (yours truly included) tried to do the next best thing, which is to implement logical “chunks” of .

Well it’s been 7 years since REC-CSS2, and those logical “chunks” have simply grown, more, chunky, as it were. They’ve also been clarified down to previously unseen levels of details in CSS2.1

You need to keep coding just to keep up.

Support CSS 2.1 NOW!

The bottom line: eventually what will happen (within a couple of years at most?) is that so many browsers will have implemented all of CSS2.1, and authors will be writing with that in mind, that any new browser that wants to support part of CSS2.1 will have to support all of it in order to support the style sheets in the wild.

IMHO, that’s called progress.

For Now

But we don’t have any fully compliant CSS 2.1 browsers yet. And we still have obsolete/abandoned browsers with enough marketshare (or machine dependence) to warrant the incremental bit of effort to support them. So for now:

  1. First try to simply author standards-based cross browser designs.
  2. Validate, validate, validate.
  3. Check any browser differences to see if your code is perhaps depending on an implicit browser default style sheet (like the example of the visible empty <legend> in IE6/Windows), and specify that styling explicitly instead of depending on the defaults.
  4. Use CSS hacks and filters sparingly (and only as needed) to get non-compliant obsolete/abandoned browsers to comply to your presentational wishes.
  5. And keep the pressure on the browser vendors to implement the web standards all of us web developers depend on to get our jobs done.

If you’ve made it this far, you’ve been extraordinarily patient and have the attention span of a savant. I wish you a happy Thanksgiving holiday.

[This entry originally posted over here.]

Return to top

Post a Reply

Comments are closed.

All of the entries posted in WaSP Buzz express the opinions of their individual authors. They do not necessarily reflect the plans or positions of the Web Standards Project as a group.

This site is valid XHTML 1.0 Strict, CSS | Get Buzz via RSS or Atom | Colophon | Legal