How does one target IE7 and IE8 with valid CSS?

CssInternet ExplorerInternet Explorer-8Web Standards

Css Problem Overview


I want to target IE7 and IE8 with W3C-compliant CSS. Sometimes fixing CSS for one version does not fix for the other. How can I achieve this?

Css Solutions


Solution 1 - Css

Explicitly Target IE versions without hacks using HTML and CSS

Use this approach if you don't want hacks in your CSS. Add a browser-unique class to the <html> element so you can select based on browser later.

Example

<!doctype html>
<!--[if IE]><![endif]-->
<!--[if lt IE 7 ]> <html lang="en" class="ie6">    <![endif]-->
<!--[if IE 7 ]>    <html lang="en" class="ie7">    <![endif]-->
<!--[if IE 8 ]>    <html lang="en" class="ie8">    <![endif]-->
<!--[if IE 9 ]>    <html lang="en" class="ie9">    <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--><html lang="en"><!--<![endif]-->
    <head></head>
    <body></body>
</html>

Then in your CSS you can very strictly access your target browser.

Example

.ie6 body { 
	border:1px solid red;
}
.ie7 body { 
	border:1px solid blue;
}

For more information check out http://html5boilerplate.com/

Target IE versions with CSS "Hacks"

More to your point, here are the hacks that let you target IE versions.

Use "\9" to target IE8 and below.
Use "*" to target IE7 and below.
Use "_" to target IE6.

Example:

body { 
border:1px solid red; /* standard */
border:1px solid blue\9; /* IE8 and below */
*border:1px solid orange; /* IE7 and below */
_border:1px solid blue; /* IE6 */
}

Update: Target IE10

IE10 does not recognize the conditional statements so you can use this to apply an "ie10" class to the <html> element

<!doctype html>
    <html lang="en">
    <!--[if !IE]><!--><script>if (/*@cc_on!@*/false) {document.documentElement.className+=' ie10';}</script><!--<![endif]-->
        <head></head>
        <body></body>
</html>

Solution 2 - Css

I would recommend looking into conditional comments and making a separate sheet for the IEs you are having problems with.

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

Solution 3 - Css

The answer to your question

A completely valid way to select all browsers but IE8 and below is using the :root selector. Since IE versions 8 and below do not support :root, selectors containing it are ignored. This means you could do something like this:

p {color:red;}
:root p {color:blue;}

This is still completely valid CSS, but it does cause IE8 and lower to render different styles.

Other tricks

Here's a list of all completely valid CSS browser-specific selectors I could find, except for some that seem quite redundant, such as ones that select for just 1 type of ancient browser (1, 2):

/******  First the hacks that target certain specific browsers  ******/
* html p                        {color:red;} /* IE 6- */
*+html p                        {color:red;} /* IE 7 only */
@media screen and (-webkit-min-device-pixel-ratio:0) {
    p                           {color:red;}
}                                            /* Chrome, Safari 3+ */
p, body:-moz-any-link           {color:red;} /* Firefox 1+ */
:-webkit-any(html) p            {color:red;} /* Chrome 12+, Safari 5.1.3+ */
:-moz-any(html) p               {color:red;} /* Firefox 4+ */

/****** And then the hacks that target all but certain browsers ******/
html> body p                  {color:green;} /* not: IE<7 */
head~body p                   {color:green;} /* not: IE<7, Opera<9, Safari<3 */
html:first-child p            {color:green;} /* not: IE<7, Opera<9.5, Safari&Chrome<4, FF<3 */
html>/**/body p               {color:green;} /* not: IE<8 */
body:first-of-type p          {color:green;} /* not: IE<9, Opera<9, Safari<3, FF<3.5 */
:not([ie8min]) p              {color:green;} /* not: IE<9, Opera<9.5, Safari<3.2 */
body:not([oldbrowser]) p      {color:green;} /* not: IE<9, Opera<9.5, Safari<3.2 */

Credits & sources:

Solution 4 - Css

For a more complete list as of 2015:

IE 6

* html .ie6 {property:value;}

or

.ie6 { _property:value;}

IE 7

*+html .ie7 {property:value;}

or

*:first-child+html .ie7 {property:value;}

IE 6 and 7

@media screen\9 {
    .ie67 {property:value;}
}

or

.ie67 { *property:value;}

or

.ie67 { #property:value;}

IE 6, 7 and 8

@media \0screen\,screen\9 {
    .ie678 {property:value;}
}

IE 8

html>/**/body .ie8 {property:value;}

or

@media \0screen {
    .ie8 {property:value;}
}

IE 8 Standards Mode Only

.ie8 { property /*\**/: value\9 }

IE 8,9 and 10

@media screen\0 {
    .ie8910 {property:value;}
}

IE 9 only

@media screen and (min-width:0) and (min-resolution: .001dpcm) { 
 // IE9 CSS
 .ie9{property:value;}
}

IE 9 and above

@media screen and (min-width:0) and (min-resolution: +72dpi) {
  // IE9+ CSS
  .ie9up{property:value;}
}

IE 9 and 10

@media screen and (min-width:0) {
    .ie910{property:value;}
}

IE 10 only

_:-ms-lang(x), .ie10 { property:value\9; }

IE 10 and above

_:-ms-lang(x), .ie10up { property:value; }

or

@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
   .ie10up{property:value;}
}

IE 11 (and above..)

_:-ms-fullscreen, :root .ie11up { property:value; }

Javascript alternatives

###[Modernizr][1]

> Modernizr runs quickly on page load to detect features; it then > creates a JavaScript object with the results, and adds classes to the > html element

###[User agent selection][2]

The Javascript:

var b = document.documentElement;
        b.setAttribute('data-useragent',  navigator.userAgent);
        b.setAttribute('data-platform', navigator.platform );
        b.className += ((!!('ontouchstart' in window) || !!('onmsgesturechange' in window))?' touch':'');

Adds (e.g) the below to the html element:

data-useragent='Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)'
data-platform='Win32'

Allowing very targetted CSS selectors, e.g.:

html[data-useragent*='Chrome/13.0'] .nav{
    background:url(img/radial_grad.png) center bottom no-repeat;
}

Footnote

If possible, avoid browser targeting. Identify and fix any issue(s) you identify. Support [progressive enhancement][3] and [graceful degradation][4]. With that in mind, this is an 'ideal world' scenario not always obtainable in a production environment, as such- the above should help provide some good options.


###Attribution / Essential Reading

Solution 5 - Css

Well you don't really have to worry about IE7 code not working in IE8 because IE8 has compatibility mode (it can render pages the same as IE7). But if you still want to target different versions of IE, a way that's been done for a while now is to either use conditional comments or begin your css rule with a * to target IE7 and below. Or you could pay attention to user agent on the servers and dish up a different CSS file based on that information.

Solution 6 - Css

The actual problem is not IE8, but the hacks that you use for earlier versions of IE.

IE8 is pretty close to be standards compliant, so you shouldn't need any hacks at all for it, perhaps only some tweaks. The problem is if you are using some hacks for IE6 and IE7; you will have to make sure that they only apply to those versions and not IE8.

I made the web site of our company compatible with IE8 a while ago. The only thing that I actually changed was adding the meta tag that tells IE that the pages are IE8 compliant...

Solution 7 - Css

I did it using Javascript. I add three css classes to the html element:

ie<version>
lte-ie<version>
lt-ie<version + 1>

So for IE7, it adds ie7, lte-ie7 ..., lt-ie8 ...

Here is the javascript code:

(function () {
    function getIEVersion() {
        var ua = window.navigator.userAgent;
        var msie = ua.indexOf('MSIE ');
        var trident = ua.indexOf('Trident/');

        if (msie > 0) {
            // IE 10 or older => return version number
            return parseInt(ua.substring(msie + 5, ua.indexOf('.', msie)), 10);
        } else if (trident > 0) {
            // IE 11 (or newer) => return version number
            var rv = ua.indexOf('rv:');
            return parseInt(ua.substring(rv + 3, ua.indexOf('.', rv)), 10);
        } else {
            return NaN;
        }
    };

    var ieVersion = getIEVersion();

    if (!isNaN(ieVersion)) { // if it is IE
        var minVersion = 6;
        var maxVersion = 13; // adjust this appropriately

        if (ieVersion >= minVersion && ieVersion <= maxVersion) {
            var htmlElem = document.getElementsByTagName('html').item(0);

            var addHtmlClass = function (className) { // define function to add class to 'html' element
                htmlElem.className += ' ' + className;
            };

            addHtmlClass('ie' + ieVersion); // add current version
            addHtmlClass('lte-ie' + ieVersion);

            if (ieVersion < maxVersion) {
                for (var i = ieVersion + 1; i <= maxVersion; ++i) {
                    addHtmlClass('lte-ie' + i);
                    addHtmlClass('lt-ie' + i);
                }
            }
        }
    }
})();

Thereafter, you use the .ie<version> css class in your stylesheet as described by potench.

(Used Mario's detectIE function in https://stackoverflow.com/questions/19999388/jquery-check-if-user-is-using-ie)

The benefit of having lte-ie8 and lt-ie8 etc is that it you can target all browser less than or equal to IE9, that is IE7 - IE9.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionWasim ShaikhView Question on Stackoverflow
Solution 1 - CsspotenchView Answer on Stackoverflow
Solution 2 - CssscragarView Answer on Stackoverflow
Solution 3 - CssJoeytje50View Answer on Stackoverflow
Solution 4 - CssSW4View Answer on Stackoverflow
Solution 5 - CssBjornView Answer on Stackoverflow
Solution 6 - CssGuffaView Answer on Stackoverflow
Solution 7 - CssTahir HassanView Answer on Stackoverflow