Use of conditional comments to target certain versions of Internet Explorer is pretty commonplace nowadays, and is generally seen as the best-practice method for including separate styles for IE.
Of course, I’ve argued in a previous article that if your IE-only styles are minimal, then you should just include them in your main stylesheet, a notion that others have echoed.
But conditional comments have some unique possibilities and quirks that maybe you haven’t considered before, or have simply forgotten. Here is an overview of some things you may not know about conditional comments.
You Can Target Every Browser Except IE
I think this is the most useful item on this list. While it would be nice to be able to target individual non-IE browsers by version, that simply isn’t possible through conditional comments. But it is possible to tell your document to display styles that will apply to every browser except Internet Explorer (all versions). Here is the syntax:
<!--[if !IE]>--> <link href="non-ie.css" rel="stylesheet" type="text/css"> <script type="text/javascript" src="non-ie.js"></script> <!--<![endif]-->
In the example syntax, I’ve included a stylesheet and a script file. I think in some cases it would be quite feasible to exclude a script file from Internet Explorer because of IE’s poor JavaScript performance. I’m actually doing that on this website. I have a script that will change the layout of the website based on resolution, and I found that IE was becoming very slow and would throw JavaScript errors for no apparent reason — so I exclude that file from running when my site is viewed with IE.
It should be noted that the Microsoft-recommended version of the above code will not validate. This is actually an altered version of what Microsoft originally recommended.
You Can Target Non-IE Plus Some Versions of IE
This is another possibility that could be practical, and is a variation on the above example of targeting everything but IE. Here’s the syntax:
<!--[if IE 7]><!--> <link href="alternate.css" rel="stylesheet" type="text/css"> <!--<![endif]-->
It’s hard to notice at first, because the above comment at first glance looks very similar to a standard conditional. But the above stylesheet will only display to IE7 along with every other non-IE browser. You’ll notice that the opening and closing if
statement sections are enclosed in comments (which hides them from the other browsers) but they also still qualify as a conditional visible to IE, so the conditional will still apply to the targeted version(s) of IE.
You can also accomplish something similar by nesting conditionals, like this:
<!--[if IE]><![if IE 7]><![endif]--> <link href="alternate.css" rel="stylesheet" type="text/css"> <!--[if IE]><![endif]><![endif]-->
You Can Use Conditionals to Customize Markup
This is something that I have to admit, I was not familiar with until quite recently (probably because I rarely use IE-only CSS). It was pointed out in the comments in a previous article but evidently was first proposed by Paul Irish.
Here’s the basic syntax:
<!--[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]-->
So, in this example, the <body>
tag gets a different class name depending on the version of IE being used. Non-IE browsers get a naked <body>
tag (the last line). Targeting IE in your stylesheet then becomes just a matter of adding .ie6
in front of your selectors.
This option works as an alternative to conditional comments, and allows you to keep all your styles in the same file in order to save HTTP requests (which would grow in number if you use extra stylesheets targeted by conditionals). I think this is great advice in light of IE’s performance issues. IE is slow enough as it is; if you can do anything to speed it up (or more accurately, prevent it from slowing down), then go for it.
You Can Target IE Versions by Decimal Points
I really don’t see the use in doing this, but technically speaking it is possible, and good to know should something like this be necessary. This targeting is referred to as targeting by “version vectors”. But apparently, you have to know the exact version vector, otherwise the conditional will fail.
Here’s an example that correctly targets IE5.0 (not that you would ever have to do this!):
<!--[if IE 5.0000]> <link href="ie5.css" rel="stylesheet" type="text/css"> <![endif]-->
It should be noted that the version vector can change according to the Windows machine being used, so the above syntax would not necessarily target all versions of IE 5.0, but only IE5.0 on certain machines. More info on this can be found here on MSDN. And there’s a very detailed explanation at the bottom of this article describing how to target specific versions of IE by version vectors.
You Can Use Other Operators in Your Expressions
Normally, the expressions we use to target IE include the use of the NOT operator (!), or one of the greater than/less than operators (gt, gte, lt, lte), but you can also use the subexpression operator (), the OR operator (|), as well as the AND operator (&).
For example:
<!--[if (IE 6)|(IE 7)]> <link href="ie6-7.css" rel="stylesheet" type="text/css"> <![endif]-->
The expression above uses parentheses combined with the OR operator to target IE6 and IE7, and nothing else. Since IE5 is out of general use, then this method has become somewhat obsolete, since you can accomplish the same thing by using “lte IE7” instead.
And here’s how you would use the AND operator (this example targets IE5 and IE6):
<!--[if (gt IE 4)&(lt IE 7)]> <link href="ie5-6.css" rel="stylesheet" type="text/css"> <![endif]-->
What Else?
I’m not sure if any of the above suggestions will be used too often, other than maybe the ability to target non-IE browsers. Conditionals have certainly saved developers many headaches, and like CSS hacks, continue to be used to create a consistent cross-browser experience.
Are there any other quirks and facts about conditionals that I haven’t mentioned here?
No, does not work.
!IE does not work.
Actually, it does. Maybe you could add some clarifying information like “I tested it in browser X on operating system Y and it didn’t work.”
It does work, you just have to make sure you’re using the right syntax. I can see many people doing the following:
But that’s not correct. You have to use this syntax:
Notice the fact that the opening and closing expressions are wrapped in comments (in the second example which hides the expressions from the non-ie browsers, but allows the link tag to be viewed by them), instead of just a single comment wrapping the whole thing, which hides it from all, except for IE, which evaluates the expression.
It also can be written as
I did not knew about subexpression operators, Thanks for shearing : )
Great article, Louis. You have 10 / 10 points.
Huh. I never thought about doing the body classes that way. Sweet! A new toy to play with!
Indeed, this seems intriguing.
Amazing Article. This goes in my bookmark for future reference. :D
Thanks a lot for sharing.
Awesome article! Really helpful for dealing with ie browsers. Thx for sharing!
If you’re already ID’ing the BODY tag (say body id=’about’), you can ID the HTML tag using conditional comments.
I’m trying to use the conditional technique to address different css coding by adding a class TO the BODY or HTML as in the example. BUT it seems that you can ONLY use conditional statements inside the BODY tag. When I run this code, all that gets output are the last items in the conditionals.
This is the View Source HTML output from IE8:
This is the View Source from Firefox 4.x:
As you can see.. the conditionals that are trying to control the HTML and Body tags do not work. Is there an error in the code or am I correct?
Joel, no matter what browser you use to view the source, the conditional comments will still look exactly the same. It’s not like a PHP variable that doesn’t get seen when you view source.
Conditional comments are always present in the source, and always look the same, no matter what browser is used to view the source.
The changes will only be evident in how the classes are used. For example, if you say “If NOT IE, add a class of “otherbrowsers” to the body tag”, then you’ll have to use that body tag’s class to actually see the results. So if you do something like:
Then the blue color text will appear in Firefox, but it will not appear for IE, because that class is only visible to non-IE browsers.
But it will *still* appear in the source code, so don’t get mixed up about that. What appears in the source for conditional comments is not necessarily what will actually affect the browser.
Great compilation, Thanks! Actually, i really dont know this CC techniques. Bookmarked.
If anyhow we have to have use of separate IE css this is “(Conditionals to Customize Markup)” something really good to go with – thanks
If you were desperate you could also use it to populate some JavaScript booleans rather that browser sniff…
I've used this in a couple of occasions where I've not had control over the whole page and was asked not to include a 50k JS library just to implement some minor features cross-broswer but was able to inject code fragments into a HTML snippet. Obviously I didn't just use it to insult IE users :-)
I use this PHP function to set a body-class depending on which OS and browser (+version) a user is running:
http://gist.github.com/512736
With this you can skip conditional tags and other hacks altogether!
Your function is not completely failsafe, because the User Agent header is customizable by the user, and some people even completely disallow it, so you cannot rely on it to do this.
Using the same technic like Simon in my CMS:
http://redaxscript.com/manual/designer/dynamic-styles
It’s way better than CC and CSS hacks…
You’ve been misinformed. This is a very unreliable method for targeting the browser. I’ll be covering this in a future article.
I use a similar technique to your “body class” one, except I use a separate div for IE instead. And then I close it up with another conditional comment at the bottom. It just seems really messy to have to copy over the body tag like that.
The operators are cool though, thanks for the tips. I’ll bookmark this.
that’s exactly what I was thinking as I read it… I too thought it’d be less clean-up later and having the multiple body tags sitting in comments. great call.
Great article on using conditionals. Thankfully IE8 does a much better job of adhering to common standards accepted by other major browsers. However, until large corporation see that IE6 and IE7 are NOT the coolest thing ever, I guess we will all have to keep writing conditionals or using some of these great tips that you have provided here!
Thanks!
This is great! I almost never use IE-only stylesheets or hacks but it’s nice to know when IE is so frustrating you just don’t feel like moving your code around to fix it anymore.
Very insightful resource. Have bookmarked it for future reference!
You can exclude IE6 and older by:
see http://hicksdesign.co.uk/speaking/css-filters
Excellent article, lots of bits there i didn’t know.
Thanks for making the time to write these articles!! I wish I could’ve run across your site a year and a half ago when I literally spent countless hours/days looking for ways to make IE6 and IE7 behave!!!!
Please, please continue to invest your time and effort on your articles and I hope there are more to come. If it weren’t for articles like these, we newbies would be in trouble!
nice article, I’ve been using these for years for IE specific script, css, and whatever.
much easier to work with than any other form of detection based on useragent strings.
Given that the only question you generally have to deal with, “is it IE or is it the rest of the world?”, and that IE in general is the cause of so many headaches, its nice of MS to provide an easy way out with CCs.
On a recent project I was slinging xsl for client side transforms, CCs came in really handy… if anyone is interested in how to write one of these in XSL… here you go.
of course you can combine with the above techniques.
html, css, js, whatever
ok … I believe you, my xmp tag was devoured, intruding on my lazyness
I like the method of assigning classes to the body element to work around the need to send extra HTTP requests to fetch the IE specific code stored in separate external CSS files. But isn’t this method prone to specificity problem?
since the code might introduce new values for existing selectors and given that it’s imperative to use selectors in CSS stylesheet to target the IE offending element, this would make the new declaration more specific ( has more weight ) and thus override the existing rule found on the same CSS file.
Your thoughts would be much appreciated
Maybe you’re not understanding how those work.
The IE-only classes will only appear to IE users. So, when they are overridden, the override is desired, because you want to target *only* IE and override whatever selector is in the normal stylesheet.
You would never do this with a selector that is not declared in the main stylesheet, because the purpose of it is to help you override. Of course, even the IE classes would be used in the main stylesheet, so you could put it right below the other one, so it’s easy to find and easy to maintain.
Doesn’t work. For “You Can Target Non-IE Plus Some Versions of IE”, IE shows this at the top of the page:
<!–[if IE 7]>
Fail.
I just tested it and it seems to work fine for me. I don’t have that problem. I’m using IETester to test IE. What version of IE are you using? Can you show a test page where you see this happening?
Lifesaver! Well, OK, a little dramatic, but this was exactly what I needed today to resolve a thorny issue. I was creating a video lightbox using the prettyPhoto jQuery plugin, but IE (of course) insisted on displaying it differently than every other browser. The problem is that there was no param that could be passed in, nor easy access to the plugin’s applicable CSS. The method given above for targeting everything <strong>except </strong> IE worked a treat. Here’s an example from the source
Note the difference in dimensions passed in IE versus all others. This resulted in the lightbox having the same appearance in all browsers, and resolved a knotty problem easily. Thanks!
Sub Expression Operators are news to me, Thanks for the useful post!
Now that IE10 is out, conditional comments are gone. What are the alternatives?
1. Code in such a way that you don’t require IE-only code (which isn’t too hard with IE10)
and
2. http://www.impressivewebs.com/ie10-css-hacks/
this no longer works
Correction: It doesn’t work in IE10 and above, unless you’re using the browser modes, but those have their own problems.
I just ran into this: I am a bit surprised that *no one* points out problems with Conditional Comments? Like that they are a maintenance tax? All I can find that quick is Jens Meiert’s work on this – see http://meiert.com/en/blog/20080824/to-be-clear/ – but that is totally missing for a balanced view. I am not a hardliner on this but I learned to stay away from Conditional Comments.