Home > front-end development > Conditional stylesheets vs CSS hacks? Answer: Neither!

Conditional stylesheets vs CSS hacks? Answer: Neither!

October 20th, 2008

From what I've seen a good number of developers these days are split between conditional stylesheets and css hacks.

You're used to seeing this:

  <link rel="stylesheet" type="text/css" media="screen" href="css/style.css" />
  <!--[if IE 7]><link rel="stylesheet" type="text/css" media="screen" href="css/ie7.css"  />< ![endif]-->
  <!--[if IE 6]><link rel="stylesheet" type="text/css" media="screen" href="css/ie6.css"  />< ![endif]-->

But probably also plenty of this:

div.infoBox { float: left; padding-right: 10px; _padding-right: 5px; }

CSS hacks to target specific browsers stay where the rest of your styles are, but they certainly don't validate. For sometime now, the standards community has rallied around conditional stylesheets as a solution to the validation problem.

There are a few problems with it though:

  • Conditional stylesheets mean 1 or 2 additional HTTP requests to download
  • As they are in the the <head>, the rendering of the page waits until they're totally loaded.
  • Also - Yahoo's internal coding best practices do not recommend conditional stylesheets
  • It can separate a single CSS rule into multiple files. I've spent a lot of time wondering "Where the eff is that rule coming from!?" when it turned out to be tucked away in a conditional stylesheet.

Here's my proposed solution:

  <!--[if lt IE 7 ]> <body class="ie6"> <![endif]--> 
  <!--[if IE 7 ]> <body class="ie7"> <![endif]--> 
  <!--[if IE 8 ]> <body class="ie8"> <![endif]--> 
  <!--[if !IE]>--> <body> <!--<![endif]-->

Using the same conditional comments, we're just conditionally adding an extra class onto the body tag. This allows us to keep our browser-specific css in the same file:

 div.foo { color: inherit;}
.ie div.foo { color: #ff8000; }

Plus it totally validates and works in all browsers.

(Hat tip to Paul Hammond and Adam McIntyre for being s-m-r-t.)

Paul Irish front-end development

  1. Matt Dolan
    | #1

    Hi. I think you're on to something… I implemented this just last month at work.

    I'm doing my detection in JSTL (its on a jsp) testing against the user agent string so have it working for all browsers. Perhaps not ideal but works for the majority of users.

    One of the great reasons to implement this from my perspective was the ease at which it is to decommission styles for now unsupported browsers. One simple search for .ie6 (if only!) and you're done. Plus if multiple browsers need the same fix no need to look in hundreds of places they'll all be there next to each other.

  2. | #2

    Whilst I like the idea of adding a class to the body tag as a way of separation, I don't really understand the first problem you mentioned.

    The HTTP requests only occur if you're using those browsers targetted, i.e. you don't get the additional requests, if you're using firefox.

    Your third point contradicts what you're saying in your post. Although it's not a conditional stylesheet per-say, you are using conditional-comments to feed conditional-css.

    Surely it's better to bloat the bad browsers with a couple of requests, than it is to bloat all browsers with unused css, example.. #ie8 .something{} won't apply to firefox, but you'll have loads of these littered in your stylesheets.

  3. | #3

    Hey Mike,
    True, the extra requests only go to IE.
    And yes, it means extra KB on the wire for non-IE.

    But on the whole, I'd think you're looking at a net gain for speed for all your users.
    If I could prove this to you with numbers I'd try. :)

  4. george
    | #4

    good idea… but this way you would invalidate your stylesheet (conditional stylesheets usually contain some hacks - e.g. zoom:1, or others.. )

    reducing amount of requests is a great idea - even at the cost of bigger file size…

    and then again, if you're doing optimization (sprites, minimize number of requests & gziping your css/js files), added filesize shouldn't be bigger than 1kb even for a huge site…

  5. Eric
    | #5

    Hammond's post turned me on to this technique. I really like it; instead of breaking out the IE fixes into one or more extra files that I have to keep up-to-date, I just add the IE or IE6 adjustments below the relevant styles.

  6. | #6

    Interesting idea, Paul. But Mike makes some very good points in his earlier comment. What he didn't mention is that the repetition makes this solution less extensible. And what happens if someone fat fingers one of the Conditional Comments and the visiting user agent decides to march forward with the wrong BODY tag? Oh boy!

    As an alternative to build on your idea, consider using script to set the value of the BODY tag's class attribute and save some repetition:

    document.body.className += " ie"

    Happy coding!

  7. michael
  8. | #8

    Yeah definitely similar..

    You can sniff on the backend, but that poses problems when it comes to caching.

  9. | #9

    You mentioned this technique on 24 ways. I think I may start using it.

    I think the reduction in http requests outweighs slightly larger stylesheets for non-IE browsers, as byte for byte the size of my IE style sheets are very very small.

    Why would the suggestion made by Josh cause caching issues?

  10. | #10

    Christopher,

    Thanks! I think it's better to develop with, too. :)

    Serverside user agent sniffing means you're delivering different pages to different people. Means more effort if you want a comprehensive caching strategy. And likely not as responsive a response.

  11. Kyle Bradshaw
    | #11

    Don't know if you were aware of this script
    http://rafael.adm.br/css_browser_selector/

    But you can target browsers via CSS inheritance with this script as well, but then again it's JS not a conditional comment so you're making concessions either way.

  12. | #12

    Good link, Kyle.

    Yeah my optimal solution would be one that works sans-javascript. (Heh, although most of the sites I make totally require javascript)

    Maybe its the anal about performance part of me. :)

    Thanks for pointing that out.

  13. Alice
    | #13

    Thanks so much for this helpful post!

  14. | #14

    FYI-
    This is an interesting application of a similar technique, by Keenora. Probably my favorite js approach I've seen.

  15. unclegrampa
    | #15

    Yes. This is a great thing for DB's to debate while actual worthwhile software is being created.

    See you in Harvard Square Paul!

  16. | #16

    This is very inspiring.
    Thanks for sharing.

  17. Me
    | #17

    Works great!! Thanks mate!

  18. swed
    | #18

    Isn't CSS hacks to target specific browsers really totally obsolet? Sure thing! It's about time to force all browser creators to fully implement the W3C Recommendations. Yes, the same recommendations we use creating web contents. By publishing a totally W3C-validated work ur, of coz, done! I don't understand why we should make any effort to balance out all the browser shortcomings. These self-imposed tasks will only postpone the proper implementation of the W3C recommendations by browser creators. If I'm wrong, please correct me.

  19. thedude
    | #19

    @george
    and what happens when you invalidate a stylesheet? absolutely nothing. except that it "doesn't validate."

    This approach is much smarter than serving multiple stylesheets.

  20. abomb79
    | #20

    @swed
    Sure we would all like to say the heck with non standard friendly browsers, but the truth is people still use them. I was in a presentation the other day given by the CEO of my company and he presented in a webex using IE6. It was a new release and I had missed a couple IE6 tweaks but luckily they were the kind of thing only a designer would notice. The point is IE6 is not dead yet. Let us hope the day is soon.

  21. | #21

    Beautiful! Conditional comments are the safest way to go and require less page hits, but its a pain to maintain multiple sheets. With this I can keep all my css in one sheet and still have safe and accurate browser detection.

  22. Erin
    | #22

    Great idea! You can get this to work in Dreamweaver by replacing the closing body tag with:
    <!–[if lt IE 7 ]> </body> <![endif]–>
    <!–[if IE 7 ]> </body> <![endif]–>
    <!–[if IE 8 ]> </body> <![endif]–>
    <!–[if !IE]>–> </body> <!–<![endif]–>

  1. | #1
  2. | #2
  3. | #3
  4. | #4

For code blocks, use <pre lang="javascript" escaped="true">. css and html4strict are also accepted.