CSS Hacks (original) (raw)
Dealing with browser inconsistencies often makes up a majority of the work for a web designer. Sometimes there is no reasonable way to accomplish a desired layout in all major web browsers without the use of some special exception rules for certain layout engines. Hacks necessarily lead to potential complications and should be avoided whenever possible, but when the circumstances require hacks to be used, it's best to know what your options are and weigh the consequences appropriately. The purpose of this article is to describe some of the CSS hacks, also called CSS filters, with the least significant potential consequences.
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.
Some of these selectors require that the document has a doctype but no processing instructions (including XML declarations). This is the ideal setup to prevent IE 6 from going into quirks mode anyway.
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:
`
TestTest
`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:
`
Test