In-CSS hacks
One of the drawbacks of conditional comments is that they require changes to the HTML source. Unfortunately, there is no equivalent to conditional comments in CSS. Instead, if you must use in-CSS hacks, you must use some other much less reliable techniques, often involving the exploitation of browser bugs.
Easy selectors
Most in-CSS hacks deal with selector bugs. The following is a list of browser version ranges and the beginnings of selectors that are known to select elements in them. Note that because these hacks rely on browser bugs or missing features, results may vary in some lesser-known or future browsers. All of these selectors use valid CSS.
- IE 6 and below
* html {}
- IE 7 and below
*:first-child+html {} * html {}
- IE 7 only
*:first-child+html {}
- IE 7 and modern browsers only
html>body {}
- Modern browsers only (not IE 7)
html>
/**/
body {}- Recent Opera versions 9 and below
html:first-child {}
Note that the hack for IE 7 and below is actually two separate selectors: one for IE 7 and one for IE 6 and below. The rest of the desired selector must be added to both parts of the hack. The two parts cannot be combined with a comma, because IE 6 and below will fail to correctly parse the selector and won't be targetted.
The above selectors will select either the
html
or body
element. This
should be used as the start of your full selector. For example, if your
desired selector is #foo .bar
and you want it to apply only to IE 7, your resulting selector will be
*:first-child+html #foo .bar
.
Warning: Due to the nature of the Opera-specific
selector and Internet Explorer 7's incorrect handling of
:first-child
, it is very
possible that the html:first-child
selector may also select in a future version of Internet Explorer, so be
careful when using it. This selector also relies on a bug, so it may be
fixed in a future version of Opera. This page also describes an
alternative method that is more of an issue to
implement but may be somewhat more dependable considering the likely
priorities of bug fixing.
Minimized attribute selectors
These hacks are based on differences in handling of attributes in
minimized form. If a tag is written <input
disabled>
, input[disabled="disabled"] {}
should select it. However, most browsers get this wrong and in different
ways.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>Test</title>
</head>
<body>
<input type="hidden" disabled id="attrhack">
<p>Test</p>
</body>
</html>
For the above markup, here are the selectors various browsers recognize
to select the p
element:
#attrhack[disabled=""]+p {}
- Firefox 1.5 and below, possibly future versions
- Safari 2.0 and below, possibly future versions
- Konqueror 3.5 and below, possibly future versions
#attrhack[disabled="true"]+p {}
- Opera 9 and below, possibly future versions
Note that neither of these selects Internet Explorer 7. Although it supports attribute selectors and adjacent sibling combinators, it doesn't seem to recognize a string value for attributes in minimized form.
Notice: Minimized attribute form is allowed in HTML but not in XHTML. This hack will not work in XHTML documents.
!important
Internet Explorer 6 and below had a problem with the
!important
identifier that caused it to
be ignored if another declaration of the same property appeared later in the
same style declaration block. This can be used to feed Internet Explorer 6
and below special property values that are ignored by other browsers.
Internet Explorer 7 fixed this issue.
Here is an example of this technique in use:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <title>Test</title> <style type="text/css">
p { background: green !important;
/* Major browsers other than IE 6 and below respect the importance immediately */
background: red;/* IE 6 and below use this value instead, even though the above was marked as important */
}</style> </head> <body class="page-body"> <p>Test</p> </body> </html>
@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.
body[class|="page-body"]
The CSS 2.1 specification isn't clear about whether or not a hyphen can
be included in the value of a hyphen-separated attribute selector. Most
browsers, including Firefox and Internet Explorer 7, Allow the
body[class|="page-body"]
selector to select an element whose start tag looks like this:
<body class="page-body">
. However,
Opera interprets the specification differently in this regard. It splits up
the attribute value by hyphens and only checks the first piece against the
attribute selector value. Obviously, if the attribute was split by hyphens,
the first piece won't have any hyphens in it, so Opera treats this selector
as a non-match. Therefore, when the proper class is applied to the
body
element, this selector matches
Internet Explorer 7 and most modern browsers except Opera. Opera may change
their behavior to match other browsers in the future, but this technique is
known to work for Opera 8 and 9.
Here is an example of this technique in use:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="en"> <head> <title>Test</title> <style type="text/css">
p { background: red;
/* Applies to all major browsers */
} body[class|="page-body"] p { background: green;/* Applies to IE 7 and most modern browsers except Opera */
}</style> </head> <body class="page-body"> <p>Test</p> </body> </html>
body[class|="page-body"] {}
selects
the body
element with the class
page-body
in IE 7 and
all modern browsers except Opera 9 and below. It may or may not
work in future versions.
- Conditional Comments
- In-CSS hacks
- Unrecommended hacks