Reputation: 7030
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?
Upvotes: 65
Views: 139851
Reputation: 19122
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.
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 */
:first-child
;
:root
;
:first-of-type
;
:not()
;
:any()
;
* ~ *
Upvotes: 9
Reputation: 71230
For a more complete list as of 2015:
* html .ie6 {property:value;}
or
.ie6 { _property:value;}
*+html .ie7 {property:value;}
or
*:first-child+html .ie7 {property:value;}
@media screen\9 {
.ie67 {property:value;}
}
or
.ie67 { *property:value;}
or
.ie67 { #property:value;}
@media \0screen\,screen\9 {
.ie678 {property:value;}
}
html>/**/body .ie8 {property:value;}
or
@media \0screen {
.ie8 {property:value;}
}
.ie8 { property /*\**/: value\9 }
@media screen\0 {
.ie8910 {property:value;}
}
@media screen and (min-width:0) and (min-resolution: .001dpcm) {
// IE9 CSS
.ie9{property:value;}
}
@media screen and (min-width:0) and (min-resolution: +72dpi) {
// IE9+ CSS
.ie9up{property:value;}
}
@media screen and (min-width:0) {
.ie910{property:value;}
}
_:-ms-lang(x), .ie10 { property:value\9; }
_:-ms-lang(x), .ie10up { property:value; }
or
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
.ie10up{property:value;}
}
_:-ms-fullscreen, :root .ie11up { property:value; }
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
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;
}
If possible, avoid browser targeting. Identify and fix any issue(s) you identify. Support progressive enhancement and graceful degradation. 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.
Upvotes: 7
Reputation: 5817
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 Check if user is using IE with jQuery)
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.
Upvotes: 1
Reputation: 3842
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>
Upvotes: 165
Reputation: 700790
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...
Upvotes: 3
Reputation: 6824
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]-->
Upvotes: 21
Reputation: 71950
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.
Upvotes: 4