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.)
12 comments ↓
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.
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.
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. :)
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...
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.
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!
Not unlike http://www.nikhilk.net/BrowserSpecificCSS.aspx
Yeah definitely similar..
You can sniff on the backend, but that poses problems when it comes to caching.
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?
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.
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.
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.
Leave a Comment