Welcome to CSS Basics. More info on this section at the bottom of this post.

How Do I Target IE7 or IE8 Using CSS Hacks?

It’s very likely that you’ve dropped support for IE6 in your designs, seeing as the worldwide share for that browser is below 5% and declining each month.

And if you’re developing websites or web apps in any technology-related niche (like web design), then IE6 visitors are probably even lower. For this website, IE6 visitors since January 1, 2011 account for about 0.5% of users, and in the last 30 days, that’s dropped to about 0.3%. You might have similar stats.

For this reason, it’s more than likely that the only CSS hacks you’ll need are for IE7 and IE8. Firstly, if you follow some basic CSS coding principles, then you might very well need no hacks or workarounds for IE7 and IE8. For the design of this blog, I currently have zero very few IE-specific hacks — so it’s obviously possible to get by without relying too strongly on hacks. (Update: I’m no longer supporting IE6 on this site, so that does help greatly).

Nonetheless, many beginners may need ways to target IE7 and/or IE8. Here I outline the best methods for doing so.

Paul Irish’s Conditional Classes

The best method, by far, is the conditional classes technique popularized by Paul Irish. Here’s how you do it:

<!--[if lte IE 7]> <html class="ie7"> <![endif]-->
<!--[if IE 8]>     <html class="ie8"> <![endif]-->
<!--[if IE 9]>     <html class="ie9"> <![endif]-->
<!--[if !IE]><!--> <html>             <!--<![endif]-->

This uses conditional comments to target certain versions of Internet Explorer, and the <html> element receives a custom class name for different versions of IE, and no class name when the browser is not IE.

Then in your CSS, you would target IE7 or IE8 like this:

.element {
	margin-bottom: 20px;
}

.ie7 .element {
	margin-bottom: 10px;
}

.ie8 .element {
	margin-bottom: 15px;
}

Every browser will have a bottom margin of 20px on the element in question, but IE7 and IE8 will have a bottom margin of 10px and 15px respectively.

It’s important to note here that although targeting IE is necessary at times, I strongly suggest you try to find a better way to fix any browser differences, and avoid using conditional classes or any of the hacks mentioned below, if at all possible. Sometimes you just need to rethink your CSS and possibly your markup, and you can avoid this extra code from the start.

CSS Hacks

Another way to target IE7 or IE8 is using hacks.

First, how to target IE7 only. There are probably more than just two ways to do this, but here are two (which is really all you’ll need):

* + html .element {
	margin-bottom: 10px;
}

(Thanks to Anthony for the tip on this first one, above)

The hack is the part of the selector that comes before .element. No other browser will recognize that selector, so the 10px bottom margin will only appear to users of IE7.

Here’s another less memorable method:

*:first-child+html .element {
	margin-bottom: 10px;
}

Yet another way to target IE7 is like this:

.element {
	margin-bottom: 20px;
	*margin-bottom: 10px;
}

The “hack” is the asterisk at the start of the line of CSS that you want to apply to IE7. The only problem here is that this will also apply to IE6. So you should only use this if you know that this hack will look fine in IE6, or if you don’t care what it looks like in IE6. So if you’ve dropped support for IE6, then this should be fine.

From my research on this subject, there does not appear to be a way to target only IE8 (and not IE6, IE7, and IE9+) with a CSS hack. The only way seems to be using a conditional comment.

However, if you’ve dropped support for IE7, then you could use the following:

.element {
	margin-bottom: 20px;
	margin-bottom: 10px\9;
}

The “hack” is the \9 following the value and preceding the closing semicolon. This will target IE8 and below, so you should only use this as an IE8-only hack if you no longer support IE6 or IE7 (because both those versions will apply the style in this hack).

Conditional Comments

Finally, you could separate your CSS for IE7 and IE8 into separate files, using conditional comments, like this:

<!--[if IE 7]>
<link rel="stylesheet" href="ie7.css">
<![endif]-->

<!--[if IE 8]>
<link rel="stylesheet" href="ie8.css">
<![endif]-->

But I do not recommend you use this method. This has two main problems: First, it separates your CSS into three different files, making it much harder to maintain. And second, you’re adding extra HTTP requests in two of the slowest browsers, making your pages load much more slowly.

So my suggestion is to use either the conditional classes or else a simple hack to target IE7 or IE8.

Questions? Clarifications?

This post is not intended to be an exhaustive reference on this subject. It's meant to provide a simple CSS tip for beginners. If you have any questions or clarifications on anything I've said here, add them to the comments. If necessary, I'll continually improve this article to keep it up to date with the latest CSS standards and best practices.

This is the CSS Basics section of Impressive Webs. These posts do not appear in the main home page feed. You can subscribe via RSS or get an email notification whenever a new post is added.

Advertise Here

58 Responses

  1. Anthony:

    *:first-child+html .element
    A tad complicated, don’t you think?

    * + html .element
    works very well, afaik.

    • You’re right. I’ve added that one as the primary one in the article.

      Thanks!

      • The difference is that some old Operas used to recognize *+html as well but not *:first-child+html, so back in these old days it was more safe to use the latter. However, those ancient Opera versions are long gone, there should be no need for :first-child anymore. *+html is fine to target the one and only IE 7.

  2. Gary:

    I use the :not pseudo class in cases when I need different CSS for the older IE’s.
    It’s valid CSS3, and I think it’s quite readable for a browser hack.

    
    .element {
      /* for old browsers, overwritten below */
     margin: 40px;
    }
    
    .element:not(#ie6or7) {
     /* for modern browsers */
     margin: 20px;
    }
    

    Start off with the base style, which will be used for IE 6 and 7. Make another selector and add :not(#ie6or7) to target modern browsers. Here you can overwrite the style for all browsers except IE6 and IE7.

  3. Scott Vivian:

    Wow, you still get 3.2% using IE6? One of the sites I run, which isn’t even technical (though perhaps a little geeky) has 21% total IE share, made up of 0.3% IE6, 2% IE7, 7.3% IE9 and 11.6% IE8. Weird, no?

    • Doh! That was a mistake on my part.

      My IE6 numbers are 0.3% — exactly what you said. I mistakenly drilled down to the IE numbers alone, and out of all my IE users, about 3% are IE6. I’ll correct that. Thanks for the heads up! :)

  4. Qbin2001:

    Targeting IE7 – underscore hack (not applies to IE6):

    .element {
    _width: 100px;
    }

  5. Lukas:

    Shouldint this work?

    
    .element {  
    	margin-bottom: 20px;  
    	margin-bottom: 15px\9; // IE8
    	*margin-bottom: 10px;  // IE7, as we overwrite IE8 hack
    }
    
    • Yes, absolutely.

      But that’s assuming that you need three different values for a single property, which would rarely be the case (at least in my experience).

      • not likely – but quite possible, maybe not for margin but other stuffs maybe. say you are using a differnet method to style in a border to avoid inner / outer differences… its always nice to see the full stack like that.

  6. Personally I’m not comfortable with the use of hacks like this. It doesn’t seem right to use a bug in the CSS parser to build a feature of your CSS.

    I remember hacks being written about ten years ago when non-IE browsers first started to gain a better market share. Shortly afterwards they were regarded as harmful practices and their use was discouraged. It’s sad to see great blogs start to recommend their usage again. Hacks go against standards, and they just seem lazy. Why teach bad habits?

    If I’m missing something I’d be happy to be enlightened.

    • For experienced developers, you’re absolutely right. Hacks should either never be used, or only as an absolute last resort.

      Unfortunately, for beginners and others with little experience developing for IE7 and IE8, and in the face of a tight deadline, there is sometimes little option but to use a hack to get things looking right.

      In some cases, hacks could even be used as temporary fixes, to roll stuff out to production on time, then re-work things later when time is not as much of a constraint.

      • Yes, those are good points. Everyone’s used a technique that they’re not proud of to get around limitations. I suppose it’s better to have a fuller understanding of the hack you’re using rather than apply it blind. It’d be good to mention why hacks are harmful when discussing them, especially if writing to rookie developers. Always nice to encourage people to write quality code :)

        • In my humble opinion, if you design for IE6 (trying to give users the same experience as in other browsers) then you have no other choice than using hacks.

          Louis says that his blog is IE hack-free, but he does not mention the fact that it looks a bit broken in IE6.

          And for people who still “fully” support IE6, I want to point out that the following targets both IE 7 and 6:

          
          .element {  
              margin-bottom: 20px;  
              *margin-bottom: 10px;  
          } 

          And that a reset would be:

          
          .element {  
              margin-bottom: 20px;  
              *margin-bottom: 10px; /* IE 6/7 */  
              _margin-bottom: 5px;  /* IE 6 */
          } 

          Using the _property hack that Louis suggested in a previous comment.

          As a side note, if I recall, MS did not fix the *property hack in IE7 on purpose. To let authors address its “issues”.
          I think there is nothing wrong in using CSS *filters* that became features.

          Imho, using CSS filters does not show “poor quality” code, it shows that you know how to style things across the board. It is certainly better than IE hacks-free styles sheets that contain things like this:

          
          body div#myDiv {  
              display:block;
              position:absolute;  
              float:left;  
          } 
          • Louis says that his blog is IE hack-free, but he does not mention the fact that it looks a bit broken in IE6.

            Yeah, I would never claim “hack free” if I was supporting IE6. I don’t think it’s possible to do that, especially when you incorporate PNGs and other modern techniques.

          • Actually, after looking again, I had completely forgotten that I was using a couple of * hacks for IE7 to get it to recognize “display: inline-block”.

            So that was a little boastful of me to say I didn’t have any IE hacks. I think there are about 4 or 5 lines of them, but if I were to avoid using inline-block, then there would probably only be one or two lines at most.

    • Kam:

      Grrrr… disgusting recommendation to use hacks. If you are not supporting IE6 then very little hacks should be required. The better option IS to use the override styles targeting specific versions of IE. Remember all those IE 5 hacks that people strung together and all of a sudden their site broke in IE6 cos those hacks were interpreted some other way?

      Conditional includes are much more elegant and spefically tell me that I am overriding something for a specific reason. My page CSS will also validate.

      If they are n00b’s then they would be better to learn it right from the start than resort to hacks and pick up bad habits.

      • “Conditional includes are much more elegant…”

        In which way?
        Conditional Comments break the separation of concerns. They mix structure with presentation and on top of that they don’t help regarding maintenance as styles for the same elements can be found across different sheets.

        Imho, using Conditional Comments is just plain wrong. It may help authors pass CSS validation, but as far as I know they are not defined in any spec. So I’m curious to know why people think they are better than CSS filters when it comes to Standards, etc.

      • Micah Henning:

        There are also many jobs (such as my own) where styling has to be accomplished without any control over the markup. Hacks are the only way to get things looking right across all major browsers when you have no ability to move around elements or use conditional CSS.

  7. Mini tip: you can use combinators inside conditional comments

    [if (IE 7) | (IE 8)]

    To target both IE 7 and 8 specifically with a single conditional comments.

  8. Rafael:

    The hack list from Paul Irish website:

    /* IE6 */
    #element { _color: blue }

    /* IE6, IE7 */
    #element { *color: blue; or #color: blue}

    /* Everything but IE6 */
    #element { color/**/: blue }

    /* IE6, IE7, IE8 */
    #element { color: blue\9; }

    /* IE7, IE8 */
    #element { color/*\**/: blue\9; }

    /* IE6, IE7 -- acts as an !important */
    #element { color: blue !ie; } /* string after ! can be anything */

    /* IE8, IE9 */
    #element {color: blue/;} /* must go at the END of all rules */

    • Micah Henning:

      I noticed IE9 also reads

      #element { color: blue\9; }

      • I think you’re right. I can’t test in IE9, (I keep a native IE8 install instead) but I tested in IE10 PP2, and it seems to work there, as well as in all the document modes (from IE5 and up).

        I’m assuming they did that for forward compatibility but I really don’t know if it still works in the latest IE10 PP.

    • *+html and * html is valid CSS, hence safe to use.

      _property: value, *property: value, property: value\9 and the like is not valid CSS. You can never be sure how browsers will process invalid code.

      I’d stay away from dirty hacks.

  9. modernizr is pretty awesome too: http://www.modernizr.com/

  10. Matt Woods:

    I like using the jquery file, CSS Browser Selector. It allows you to define CSS for any OS, browser, or device in your CSS like this

    .win .ie7 .classname {content}

    Here us the link: http://t.co/kE8qfpbH

  11. Adi Shar:

    Hi Louis,
    Thanks, You have really provided a detailed explanation of the way CSS works on IE7 and IE8.
    I have an issue in CSS.I want different margin-top for IE 7 and IE 8 , but none of the solutions provided above work i.e. either I craete 2 seperate CSS files also.
    Its kind of a deadlock, if it works on IE 7 it will not work on IE 8 and vice-versa.

    Is it possible to have difgferent CSS classes for IE 7 and IE 8.

  12. I just had a site viewer send me an email stating “On IE8 the main content comes up in one very narrow column.” I am a Mac user, not a coder. This is a “free” site for a club I belong to so want to curb discontent when possible.
    The site is http://www.nwodga.org

    What do I need to post [here] to get an answer as to how to fix the problem? I read through your posts but am still not sure how to proceed…

    Is there any code you can add to the html that tells IE 7-8 to just go fly a kite? :-)

    • Hi Patty.

      I just tested that site in IE8, and I don’t see the problem the viewer is claiming. I have a native install of IE8, too, so it’s not just one of those standalone versions that isn’t always accurate.

      • Thanks Louis.
        Is there a general line of code that will over-ride IE’s defaults? Seems to me I heard that at one point.

        • I’m not sure exactly what you mean by that…? Override what defaults?

          • It seems to me that I was told IE displayed web pages by using default settings. I don’t know if it was just type sizes, or styles, had anything to do with page structure. It is one of those areas that I don’t really understand: what is it about IE that makes it display things differently?

            It hasn’t been a huge deal until lately. Now that I am trying to use CSS driven designs it seems displaying issues are popping up. I must be missing something. Never a lack of things to learn! Thanks.

          • You might be thinking about the effects of a CSS reset. For info on CSS resets, see section #1 in this post:

            http://www.impressivewebs.com/cross-browser-css-workflow/

            There are lots of good links covering the history of CSS resets. IE has probably been the main reason for the need for resets, so that might be what you had in mind.

  13. Validator:

    Hacks are to be preferred over conditional comments if you are opting for speed. Using modernizr is also a slowdown. Both modernizr and additional stylesheets require extra HTTP requests. Bad for performance.

  14. Matrix:

    Is ok to use that on my css ?
    input[IE 8]{
    background-color:lime !important;
    }

  15. Tony:

    I don’t see what the problem with using the filters * \9 , works and I can keep all my css in one stylesheet

  16. The provided conditional classes solution is wrong because for IE < 7 and IE 9 there’s no opening <html> tag. Even though the tag is optional in HTML 4 and HTML5 (not in XHTML 1 and polyglot HTML5/XHTML5), keep in mind that this is the place where you should specify the language of the document, so the tag is needed.

    To make sure to have an openening tag in all browsers, use

    <!--[if lte IE 7 ]><html class="ie7"> lang="en"><![endif]-->
    <!--[if IE 8 ]><html class="ie8" lang="en"><![endif]-->
    <!--[if IE 9 ]><html class="ie9" lang="en"><![endif]-->
    <!--[if gt IE 9]><!--><html lang="en"><!--<![endif]-->

    That’s pretty much what Paul Irish suggests. Remarks:
    1. I’ve left out IE 6 off the game; it gets the class “ie7″ which is probably better than no class.
    2. !IE should not be necessary in the last line; non-IEs don’t recognize the code in comments anyway
    3. Don’t use lang="en" for non-English content but set the value accordingly

    As you can already see, a drawback is that you have to repeat all attributes of the html element. There might be more than just @lang: more classes or a page ID, a namespace in XHTML/polyglot HTML5… And you might end up with

    <!--[if lte IE 7 ]><html xmlns="http://www.w3.org/1999/xhtml" id="myPageId" class="myClass ie7"> lang="en" xml:lang="en"><![endif]-->
    <!--[if IE 8 ]><html xmlns="http://www.w3.org/1999/xhtml" id="myPageId" class="myClass ie8" lang="en" xml:lang="en"><![endif]-->
    <!--[if IE 9 ]><html xmlns="http://www.w3.org/1999/xhtml" id="myPageId" class="myClass ie9" lang="en" xml:lang="en"><![endif]-->
    <!--[if gt IE 9]><!--><html xmlns="http://www.w3.org/1999/xhtml" id="myPageId" class="myClass" lang="en" xml:lang="en"><!--<![endif]-->
    • This post was mainly concerned with discussing solutions for targeting IE7 and IE8, so that conditional classes example wasn’t meant to be complete. But since people will probably copy and paste it, I will update it. It’s actually also missing an HTML tag for IE9, to be honest.

      Regarding “!IE”: It’s true non-IE browsers won’t read that anyhow, but I suppose it’s good for readability, so the developer knows which tag is seen by the other browsers.

      Also, your example uses “gt IE 9″, but that’s a bit useless because IE10+ don’t support conditional comments. So it might as well be “!IE”, simply for readability.

      • You’re right that for browsers !IE would do as well as gt IE 9. But since IE 10 is an IE, !IE seems less appropriate than gt IE 9 to me. You have a point to include both for readability for human developers, though.

    • In order to keep the markup clean and DRY (no pun intented), the “ie7”/“ie8”/“ie9” classes could be set with JavaScript – not using User-Agent sniffing, but conditional compilation and the IE-specific document.documentMode:

      /*@cc_on document.documentElement.className += ' ie' + (document.documentMode  || 7); @*/

      If you still need to tell IE 6 apart from IE 7, you might use the hacky

      /*@cc_on document.documentElement.className += ' ie' + (document.documentMode  || (window.XMLHttpRequest ? 7 : 6)); @*/

      To set a “ie10” class as well (not sure you would need such):

      var ieversion = document.documentMode /*@cc_on || 7 @*/;
      if (ieversion) document.documentElement.className += ' ie' + ieversion;

      For Opera:

      if (window.opera) document.documentElement.className += ' opera';

      Adding the Opera version would be possible with the window.opera object.

      However, keep in mind that depending on JavaScript might not be a good idea.

  17. But I do not recommend you use this method [conditional comments]. This has two main problems: First, it separates your CSS into three different files, making it much harder to maintain. And second, you’re adding extra HTTP requests in two of the slowest browsers, making your pages load much more slowly.

    The second is not an issue when you have not just additional rules for IE 7 and 8, but all the styles in the stylesheet files ie7.css and ie8.css, and don’t load the standard.css for those browsers, like so:

    <!--[if lte IE 7 ]><link rel="stylesheet" href="ie7.css"><![endif]-->
    <!--[if IE 8 ]><link rel="stylesheet" href="ie8.css"><![endif]-->
    <!--[if gte IE 9]><!--><link rel="stylesheet" href="standard.css"><!--<![endif]-->

    I agree that maintainability is a real problem here. Once you make changes in standard.css you might forget to change ie7.css and ie8.css as well. That’s why I used to raise my voice against separate stylesheets for older IEs.

    However, with a CSS preprocessor you can have the best of both worlds: multiple stylesheets for various browsers generated from one single maintained source file.

  18. Sweety:

    can we use common hack for all IE7,8, & 9? do we have any such hack?

    • Yes, you can do this in your HTML:

      
      <!--[if lte IE 9]> <html class="oldie"> <![endif]-->
      

      Then in your CSS you target IE9 and lower, by doing:

      
      .oldie {
          /* styles for IE7-9 go here */
      }
      

      And this would also target IE6, so if you need separate ones for IE6, then just add another line to your HTML to create a seperate class for IE6.

      Not technically a “hack” but it will do what you’re asking for.

  19. Katie:

    I am designing a site and it is on my testing server http://www.krtesting.com. It works great in Safari and Firefox but IE is the problem, like in most cases. Does anyone have any advice? I designed the site in Dreamweaver. I have got to get the spry menubar to stay in the correct space, drop down to work in IE and fix my floats. The 3 px bug is the problem I think. I have never had this problem before. Any advice would be appreciated. Thank you.

    • Katie, I can’t figure out what’s wrong with that menu in IE8. But you need to do a few things:

      1) Validate your CSS. You have a section of CSS that looks like this:

      
      /* The outermost container of the Menu Bar, an auto width box with no margin or padding */
      ul.MenuBarHorizontal
      {
      	/* NEW RULES Courtesy of PVII http://www.projectseven.com */
      .spry-menubar:before, .spry-menubar:after {
      content: "";
      display: table;
      }
      .spry-menubar:after {
      clear: both;
      }
      .spry-menubar {
      zoom: 1;
      text-align: center;
      }
      .MenuBarHorizontal {
      display: inline-block;
      }
      	margin: 0;
      	padding: 0;
      	list-style-type: none;
      	font-size: 100%;
      	cursor: default;
      	width: 960px;
      	background: #000;
      	text-align: center;
      	float: none;
      	height: auto;
      	position: absolute;
      }
      

      If you look closely, you’ll see the curly braces are all messed up (not enough, too many, etc). That might not be causing the problem. From what I can tell, the problem is caused by the Spry menu script, because it seems to happen when the script is triggered.

      2) The other thing you should do is create a reduced test case so you can narrow down what the problem is.

      But if that’s too difficult for you, then I’d recommend a simpler drop-down menu solution. The Spry menu does not seem very easy to use, and seems too bloated for what you’re trying to accomplish. I would try something like Twitter Bootstrap’s dropdowns or Chris Coyier’s simple drop-downs.

  20. Hey your blog messed up in IE8!! :)

  21. * + html thing worked for me, great article.

    Thanks
    Dhanesh Mane

  22. Kristin:

    THANK YOU!!! This article is fantastic and EXTREMELY insightful into IE hacks done, well, in an organized fashion so to speak. Good read! Bookmarked for sure!

  23. Prawira Putra:

    wow, thanks bro!!

  24. Aaron:

    Unfortunately the \9 hack is rendered in IE10. Hacks are bad, mmkay?

  25. Thanks for your article, it’s helpful for me.

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field. If you use keywords, your comment will be deleted, or your name will be replaced with the alias from your email address. No foul language, please. Thank you for cooperating.

Instructions for code snippets: Wrap inline code in <code> tags; wrap blocks of code in <pre> and <code> tags. When you want your HTML to display on the page in a code snippet inside of <code> tags, make sure you use &lt; and &gt; instead of < and >, otherwise your code will be eaten by pink unicorns.