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.

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.

@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.