24 ways

to impress your friends

Avoiding CSS Hacks for Internet Explorer by Kimberly Blessing

Back in October, IEBlog issued a call to action, asking developers to clean up their CSS hacks for IE7 testing. Needless to say, a lot of hubbub ensued… both on IEBlog and elsewhere. My contribution to all of the noise was to suggest that developers review their code and use good CSS hacks. But what makes a good hack?

Tantek Çelik, the Godfather of CSS hacks, gave us the answer by explaining how CSS hacks should be designed. In short, they should (1) be valid, (2) target only old/frozen/abandoned user-agents/browsers, and (3) be ugly. Tantek also went on to explain that using a feature of CSS is not a hack.

Now, I’m not a frequent user of CSS hacks, but Tantek’s post made sense to me. In particular, I felt it gave developers direction on how we should be coding to accommodate that sometimes troublesome browser, Internet Explorer. But what I’ve found, through my work with other developers, is that there is still much confusion over the use of CSS hacks and IE. Using examples from the code I’ve seen recently, allow me to demonstrate how to clean up some IE-specific CSS hacks.

The two hacks that I’ve found most often in the code I’ve seen and worked with are the star html bug and the underscore hack. We know these are both IE-specific by checking Kevin Smith’s CSS Filters chart. Let’s look at each of these hacks and see how we can replace them with the same CSS feature-based solution.

The star html bug

This hack violates Tantek’s second rule as it targets current (and future) UAs. I’ve seen this both as a stand alone rule, as well as an override to some other rule in a style sheet. Here are some code samples:

* html div#header {margin-top:-3px;}

.promo h3 {min-height:21px;} * html .promo h3 {height:21px;}

The underscore hack

This hack violates Tantek’s first two rules: it’s invalid (according to the W3C CSS Validator) and it targets current UAs. Here’s an example:

ol {padding:0; _padding-left:5px;}

Using child selectors

We can use the child selector to replace both the star html bug and underscore hack. Here’s how:

  1. Write rules with selectors that would be successfully applied to all browsers. This may mean starting with no declarations in your rule!

    div#header {}

    .promo h3 {} ol {padding:0;}
  2. To these rules, add the IE-specific declarations.

    div#header {margin-top:-3px;}

    .promo h3 {height:21px;} ol {padding:0 0 0 5px;}
  3. After each rule, add a second rule. The selector of the second rule must use a child selector. In this new rule, correct any IE-specific declarations previously made.

    div#header {margin-top:-3px;}
     body > div#header {margin-top:0;}

    .promo h3 {height:21px;} .promo > h3 {height:auto; min-height:21px;} ol {padding:0 0 0 5px;} html > body ol {padding:0;}

Voilà – no more hacks! There are a few caveats to this that I won’t go into… but assuming you’re operating in strict mode and barring any really complicated stuff you’re doing in your code, your CSS will still render perfectly across browsers. And while this may make your CSS slightly heftier in size, it should future-proof it for IE7 (or so I hope). Happy holidays!

About the author

Kimberly Blessing is a Web development and Internet business consultant for KimmieCorp. She specializes in standards implementation and site optimization and is a member of the Web Standards Project. Her personal crusade is to increase the number of women in technology-related fields.

Your comments

  1. § Weiran:

    Excellent, that certainly beats the other two hands down. But how does it compair with using conditional comments?

  2. § Derek:

    I was wondering the same thing myself: what about conditional comments?

  3. § Chasen Le Hara:

    Exactly what I was thinking. I think that everyone should be using conditional comments to target IE and the remainder of CSS hacks should be for browsers such as IE 5 Mac.

    One more thing: the second sentence of the third paragraph should begin with “In particular”.

    -Chase

  4. § Ashley Bowers:

    Not to beat a dead horse but I have the same question what about the conditional comments? Will be interesting to see if it does indeed future proof it for ie7.

  5. § Martin:

    I thought about conditional comments when I started reading this, but knowing the three simple rules in CSS hacks is good enough for me.

    You don’t need conditional comments to write a good hack.

  6. § Sebastian:

    A hack is a hack, chances are that IE7 will have it’s share of bugs, and then our little hacks will do us no good.

    Conditional comments are the way of the future. I try to use it on evry big site. Would never sell a webpage page with hacks. During testing I use hacks ofcource.

  7. § trovster:

    What future UAs does the Star hack target? I’m sure the IE7 team specifically said they’re removing it. Therefore I see it as valid as the child selector “work-around”.

    The IE team said conditional elements as the best way of targetting that browser, why not use them? We can easily target any version we want?

    I don’t think removing or changing these hacks will affect how IE7 handles, IF the browser supports what they say it will.

    If they fix the CSS support so it’s more like Firefox or Safari, then remove the hacks, then 1) it won’t get the hack rules 2) it’ll correctly apply the correct rules. And everyone is happy.

    Saying that, though, is a big IF. Conditional elements are “officially” supported by IE, so why not use them. My ownly arguement is that it requires extra MARKUP…

  8. § Hagge:

    The star hack is an interpretation error.

    The child selector is a feature of CSS.

    Conditional comments requires extra markup too.

  9. § Johan:

    The thing with conditional comments is this:

    Absolutely fine if the document is served as text/html. Although you will have to keep track of additional css-files.

    If the document is served as XML, the conditional comments produce parser errors (Yes. It’s still a proprietary technique from MS).

    And imho a hack is not a hack. Using the standard implementation of CSS to feed different styles to different browsers is perfectly good (e.g. the child selector).

    The ’* html’-hack in fact is a nonsense rule. Correctly interpreted it can’t apply to any element.

    And for anyone who is interested in CSS-hacks/-filters should read this article: Pandora’s Box (Model) of CSS Hacks And Other Good Intentions [by Tantek Celik]

  10. § Gerben:

    Your sollution violates Tantek’s third rule. It should be ugly. It just isn’t, although you could argue that it ain’t a hack.

    I’m not convinced this is the right way to do things. The method you suggest will not only target IE but also Netscape 4 and ICab 2 and any future browser that doesn’t fully implement the CSS spec. (which is very likely as we seen in the past)

    the ’* html’ hack is way more future proof and only targets IE.

    IE7 won’t ‘support’ it and I wouldn’t call IE6 a ‘current browser’ like you do.

    I’ll just continue using my * html :-)

  11. § patrick h. lauke:

    hmmm…how does the star hack violate the second rule? discuss…

  12. § nicegal:

    anyone know richard york who wrote a book on style sheet. where is he now ?

  13. § Kevin Lawver:

    The underscore hack is valid. The validator is broken. The underscore hack is brilliant for one very important reason: it keeps your hacks simple and grouped with the property being replaced. Therefore, it’s easier to go back in the future and remove or change them if needed.

    Child selectors are great, but they’re backwards from what we actually need: styles that only apply to IE for Windows, because it’s the one that’s broken. Creating new selectors somewhere after the original is hard to maintain because the hacks are no longer grouped by what’s being overridden.

    Other than that, awesome article!

  14. § Matt G:

    “hmmm…how does the star hack violate the second rule? discuss…”

    According to Tantek it does, because IE6 is a current UA. I personally think it’s a valid hack because it’s targetting a pretty obtuse interpretation problem found only in IE6-, where the pattern of selectors is made valid by IE’s understanding that there is a mystery parent element of html in the DOM.

    If there was a reasonable expectation that this wrong interpretation will be implemented into a new browser then it would definately be a bad idea for a hack. Considering that at the moment it’s an IE only thing, and that the fix in IE7 means the * html slectors won’t match and therefor won’t be rendered, I don’t see a problem.

    However, conditional comments are the way to go. Why put hacks in a clean master stylesheet when they can be seperated out and place in stylesheets that can target specific versions of IE? And they can be used in XML/XSL without parsing errors, you just need to CDATA and a couple of encoded characters for < and >.

  15. § Joey A. Tyson:

    Patrick, I’ve asked on several sites what the deal with * html is. I see it as a hack which is guaranteed to target IE5.x and 6.x only, so I write clean code and use it as an override to correct bugs found in only those browsers.

    And Matt, to answer your question, it means maintaining multiple stylesheets. I find it much easier to have one stylesheet where the IE corrections are right with my original style declarations (using * html).

  16. § gareth:

    “According to Tantek it does, because IE6 is a current UA”

    If the * hack violates the 2nd rule because IE 6 is current, by the time IE 7 comes around (and we have to worry) will IE 6 be counted as outdated and the * hack cease to violate the 2nd rule?

  17. § pawel:

    So we have changed:

    div#header { margin-top:0; } * html div#header {margin-top:-3px;}

    To:

    div#header {margin-top:-3px;} body > div#header {margin-top:0;}

    In both cases IE7 will get { margin-top:0; } (it won’t parse * html, but it will understand child selector).

    Do I miss something or there’s no difference?

  18. § reieRMeister:

    @Johan:

    Conditional comments work perfectly even when serving application/xml. Since they are valid comments they shouldn’t produce any parsing errors (look at my homepage – I am using conditional comments).

    @all:

    But there’s another problem with conditional comments: It’s not possible to combine them (at least not in a clever way).

    So if I want to hide any CSS from IE < 5, serve one specific CSS to IE >= 5 and IE < 7 and another specific CSS to IE >= 7 I run into big problems… But maybe someone knows a solution to this.

    Greetings.

  19. § Chris Hunt:

    This article advocates using “html >” to target most non-IE browsers, instead of ”* html” to target IE 6-. It’s no worse, but is it any better? I’ll need a better reason than “because tantek says so” to banish * html from my code.

    It’s simple. It works. Why change it?

    PS: “Why not use coditional comments?” Because I’d have to clutter up every page of my site with them, rather than keeping all my if-this-browser-do-this code in one place.

  20. § David Smith:

    Hacking. Unhacking. Forking code. Wow, I came here for a way to impress my friends but no one can decide the best way to do it. I’m all for not having to use hacks. At the same time I would rather not fork my css either. I can just imagine…

    This stylesheet for this browser and this one for that and so and so on. Forking might be easier on a small site and hacks could be good for larger. Its up to the browser developers. Everythings gonna change next year anyways, then we will all be having this same discussion. See you all soon and thank you Kimberley for a great idea and stirring things up a bit. :’)

  21. § Douglas Clifton:

    If you’re going to fork your code (I just love that expression, thanks) do so only in general/global terms. Layout properties, for instance. I use conditional comments to load an IE specific stylesheet that sets height and width, since these behave in the same way as their min-equivalents in browsers that implement CSS correctly.

  22. § Nick Fitzsimons:

    @Chris Hunt: I’m not sure I follow your P.S. objection to conditional comments (CCs).

    I use a standard stylesheet which works for real browsers, and a second stylesheet containing IE-specific fixes. The IE-fixup stylesheet is hauled in using a link element inside a CC, to save real browsers the trouble of downloading it.

    The CC adds exactly 32 characters (including whitespace) to each page, which is hardly “cluttering”, given that the link element necessary to bring in the fixup stylesheet is already 48 characters plus the length of the value of the href attribute. And all my fixes remain in one place.

  23. § Rich Rich Man:

    I’ve never ‘hacked’ css, only ever used the child selectors to override IE attributes with Firefox ones.

    eg

    #header{margin:3px 0 5px 10px;}

    html>body #header{margin-top:5px;}

    1st is IE, 2nd Firefox.

    If IE7 supports child selectors, it looks like I’m in > trouble.

  24. § brent:

    @Nick: “Real” browsers. I’ll be laughing about that one for a long time.

  25. § BTreeHugger:

    I feel the star-html hack and child selector hacks are both legitimate: one hides CSS from IE, the other hides it from pretty much all browsers but IE. Typically, you want the choice that reduces the amount of CSS you are “over riding”, and requires the least maintenance.

    The risk here is that IE7 introduces problems but no way to “hack” around them. If the star-html hack is fixed and most selectors are implemented, we’ll probably need horrible, inaccurate hacks or conditional comments.

    If CSS blocks had their own conditional comments, I’d use them. But having to introduce more markup is tedious, introducing a level of separation for what is often one or two hacks on an entire page. Instead of reducing maintenance requirements I’ve found c.comments increase them, especially on small sites.

    This is why I wish the W3C would create a standard extension to media queries to let us just target specific versions of engines.

  26. § vostojin:

    What about IE epecific dynamic properties in CSS?

    I have some ideas how to use it to serve IE specific style: just use proper standard CSS and apply all IE-spec stuff in expression() —only IE will see it. But I still need to explore this technique…

    What is the point of targeting all browsers with hacks? It leeds us into problems in future. Keeping with standards and pushing browse makers to support standards is the only right way ahead. Tommorow all browsers will be standards based and our current css will bother them.

  27. § pathagoros:

    Thanks so much for sharing. It works great and is far cleaner than the other two methods.

  28. § BTreeHugger:

    The point of targeting browsers is really only a question of targeting bugs in their engines.. while it’s hopefully true that “someday all browsers will be standards-based”, the occasional bug must slip through.. sometimes these bugs ruin a design, and must be worked-around as there is no alternative method that provides correct results.

    The bottom line is that the child selector hack this article advocates is still a hack; it’s perfectly valid, but so is the star-html hack. Use whichever causes you the least frustration at the time, and will prevent a maintenance nightmare. One of my peers only uses the child selector hack, and I recently noticed that by using the star-html instead his stylesheet was less than half of it’s original size.

    I still remain unconvinced that one of these two hacks is better then the other in a general sense. Even if IE7 is released and fixes these bugs, we’ll still have to support IE5 and IE6 for quite some time. In this context the star-html hack would no longer “violate” Tantek’s second rule. Just understand how each hack works and use it appropriately.. try to keep your CSS size down, and use the right tool for the job.

  29. § Adam van den Hoven:

    The Holly Hack solves a multitude of IE’s more annoying bugs. Does anyone see a problem with putting the following in ALL your CSS as the first item:

    * { height: 1%;}

    html>body * { height: auto; }

    I think this works, although I’ve never tried it.

Commenting is closed for this article.

24 ways: day 17