SELECTOR HACKS
/* IE 6 and below */
* html #uno { color: red }
/* IE 7 and below */
*:first-child+html #dos { color: red }
/* IE 7 and modern browsers */
html>body #tres { color: red }
/* Modern browsers (not IE 7) */
html>/**/body #cuatro { color: red }
/* Opera 9.27 and below */
html:first-child #cinco { color: red }
/* Safari */
html[xmlns*=""] body:last-child #seis { color: red }
/*safari 3+, chrome 1+, opera9+, ff 3.5+ */
body:nth-of-type(1) #siete { color: red }
/* safari 3+, chrome 1+, opera9+, ff 3.5+ */
body:first-of-type #ocho { color: red }
/* saf3, chrome1+ */
@media screen and (-webkit-min-device-pixel-ratio:0) {
#diez { background: #FFDECE; border: 2px solid #ff0000 }
}
ATTRIBUTE HACKS
/* ie6 and below */
#once { _color:blue }
/* ie7 and below */
#doce { *color: blue } /* or #color:blue */
/*IE8 Standards-Mode Only:*/
.test { color /*\**/: blue\9 }
All IE versions, including IE8 Standards Mode:
.test { color: blue\9 }
/* 'Modern Browsers' includes IE8, whether you agree or not.. :) */
How browser detection using CSS hacks works
The way browser detection using
CSS hacks works is to send one
CSS rule to the browser(s) you're trying to trick, and then send a second
CSS rule to the other browsers, overriding this first command. If you have two
CSS rules with identical selectors then
the second CSS rule will always take precedence.
Say for example you wanted the space between your header area and the content to have a gap of 25px in Internet Explorer, or
IE as it's affectionately known. This gap looks good in
IE but in Firefox, Opera and Safari the gap is huge and a 10px gap looks far better. To achieve this
perfect look in all these browsers you would need the following two
CSS rules:
#header {margin-bottom: 25px;}
#header {margin-bottom: 10px;}
The
first command is intended for IE, the second for all other browsers. How does this work? Well, it won't at the moment because
all browsers can understand
both CSS rules so will use the second
CSS rule because it comes after the first one.
By inserting a
CSS hack we can perform our browser detection by hiding the second
CSS rule from
IE. This means that
IE won't even know it exists and will therefore use the first
CSS rule. How do we do this? Read on and find out!
Browser detection for Internet Explorer
To send different
CSS rules to
IE, we can use the
child selector command which
IE can't understand. The child selector command involves two elements, one of which is the child of the other. So,
html>body
refers to the child,
body
, contained within the parent,
html
.
Using the example of the header margin, our
CSS command would be:
#header {margin-bottom: 3em;}
html>body #header {margin-bottom: 1em;}
IE can't understand the second
CSS rule due to the
html>body
CSS command so will ignore it and use the first rule. All other browsers will use the second rule.
Browser detection for Internet Explorer on the Mac
Quite simply,
IE on the Mac does strange things with
CSS. The browser's become somewhat obsolete as Microsoft aren't going to be bringing out an updated version. As such, many web developers code their
CSS-driven sites so that the site works in
IE/Mac, although it
may not offer the same level of advanced functionality or design. Provided
IE/Mac users can access all areas of the site this is seen as a suitable way of doing things.
To hide a command using the
IE/Mac CSS hack1 is simple, and involves wrapping a set of dashes and stars around as many
CSS rules as you like:
/* Hide from IE-Mac \*/
#header {margin-bottom: 3em;}
#footer {margin-top: 1.5em;}
/* End hide */
IE/Mac will simply ignore all these commands. This
CSS hack can actually be quite useful if there's a certain area of the site not working properly in
IE/Mac. If that section isn't fundamental to being able to use the site, you can simply hide it from
IE/Mac like so:
#noiemac {display: none}
/* Hide from IE-Mac \*/
#noiemac {display: block;}
/* End hide */
The first
CSS rule hides the entire section assigned the noiemac id (i.e.
). The second
CSS rule, which
IE/Mac can't see, displays this section.
@import "non-ie.css" all
Internet Explorer 7 and below don't support media selectors on
@import
rules, instead ignoring the entire rule when they are present. Therefore, you can create an entire stylesheet for non-IE browsers and import it into your main stylesheet by adding
@import "non-ie.css" all;
.
Future versions of Internet Explorer may support the
@import
rule correctly.
@import "stylesheet.css" all;
imports the stylesheet in
all major browsers except IE 7 and below. It may or may not work in future versions of IE.
Unrecommended hacks
_property: value and -property: value
Due to a parsing error, Internet Explorer 6 and below wouldn't fail on properties that were prefixed with non-alphanumeric characters. Prefixing a regular property name with
_
or
-
will cause the property to be applied to Internet Explorer 6 and below but generally not in other browsers. Internet Explorer 7 had this bug fixed.
The CSS specification allows browsers to use an underscore (
_
) or hyphen (
-
) as a prefix for a vendor-specific property name with the guarantee that such properties will never be used in a future CSS standard. Because of this guarantee, these two prefix characters are ideal options for this hack.
Although the CSS specification defines this vendor-specific property syntax, the properties are inherently not part of any W3C-endorsed CSS profile and are therefore invalid when validated against one. For this reason, and because there is an
often acceptable alternative, this hack is unrecommended.
_property: value
and
-property: value
apply the property value in
IE 6 and below. Warning: this uses
invalid CSS.
*property: value
Although Internet Explorer 7 corrected its behavior when a property name is prefixed with an underscore or a hyphen, other non-alphanumeric character prefixes are treated as they were in IE6. Therefore, if you add a non-alphanumeric character such as an asterisk (
*
) immediately before a property name, the property will be applied in IE and not in other browsers. Unlike with the hyphen and underscore method, the CSS specification makes no reservations for the asterisk as a prefix, so use of this hack could result in unexpected behavior as the CSS specifications evolve.
*property: value
applies the property value in
IE 7 and below. It may or may not work in future versions. Warning: this uses
invalid CSS.
body:empty
The
:empty
pseudo-classes is proposed for CSS 3 and should select an element that has no elements or text inside it. However, when used on the
body
element, Firefox 1.5 and 2.0 (and corresponding versions of other Gecko-based browsers) always select it even when the body has content (which it should always have).
Although this hack is expected to be valid in CSS 3, it has not yet reached W3C Recommendation status and is invalid CSS 2.x, so it currently isn't recommended to use this hack. However, it is probably the best way to single out recent versions of Firefox.
body:empty {}
selects the
body
element in
Firefox 1.5 and 2.0 only. It may or may not work in future versions. Warning: this uses
invalid CSS 2.x but
valid CSS 3 according to recent drafts.
html*
Internet Explorer 7 fixed the quirk that allowed the universal selector (
*
) to select some nonexistent parent of the
html
element, but there's another issue that they didn't fix: When a universal selector is directly adjacent to another simple selector without a space between, Internet Explorer 7 assumes a space there. That means that
html*
is treated by IE7 like
html *
, while other browsers ignore it because it's a parsing error. Similarly, IE7 treats
**
like
* *
.
html* {}
selects all descendants of the
html
element in
IE 7 and below. It may or may not work in future versions. Warning: this uses
invalid CSS!
!ie
Internet Explorer 7 fixed one of the issues with the
!important
identifier, but it still has problems when the identifier has an error in it. If an illegal identifier name is used in place of
important
, Internet Explorer 7 and below will handle the property normally instead of failing. Therefore, in any style declaration block, you can include properties intended to only apply to Internet Explorer and add an
!ie
identifier. Almost any word can be used in place of
ie
.
The
!ie
identifier allows the property to be applied in
IE 7 and below. It may or may not work in future versions. Warning: this uses
invalid CSS!
!important!
Another problem with the
!important
identifier that wasn't fixed in IE 7 is the treatment of non-alphanumeric characters after the identifier. Normally, this should cause the property to fail, but Internet Explorer 7 and below ignore the additional punctuate and apply the property as if it just had the
!important
identifier.
The
!important!
identifier allows the property to be applied with importance in
IE 7 and below and the property is not applied in other browsers. It may or may not work in future versions. Warning: this uses
invalid CSS!