CSS hacks

Share on TwitterShare on TumblrSubmit to StumbleUponSave on DeliciousDigg This

The so-called “CSS hacks” are particular patterns used by authors to deliver style rules only to one browser or to prevent a browser from reading certain rules that might cause rendering problems. These patterns may rely on parsing bugs, wrong DOM implementations or syntactical constructs supported only by the targeted browser. Hacks may validate or not. In this article I’ll review the most popular hacks used by authors, explaining why such patterns should be avoided and how one can actually target a browser by deploying other techniques.

Table of contents

The Box Model hack

This hack is used in order to hide style rules from Internet Explorer 5 Windows. It relies on a parsing bug related to the correct handling of escaped sequences inside strings. The pattern is the following:

Listing 1. The Box Model hack

  1. body {
  2. font-size: x-small;
  3. voice-family: "\"}\"";
  4. voice-family: inherit;
  5. font-size: small;
  6. }

The voice-family property is used only as a container of the escaped sequence, since this is an aural property that has no effect on the visual rendering of a document (note, however, that its first value is then overridden by the inherit value). Internet Explorer 5 reads first the ‘{‘ token (interpreted as the end of the declaration block) and then an escape (‘\’) that hides the following declarations. In other words, Explorer 5 can only read the first declaration of the block.

The Tan hack

This hack is used in order to hide style rules from Internet Explorer 5 Windows. It relies on a parsing bug related to the correct handling of escapes inside property names. The pattern is the following:

Listing 2. The Tan hack

  1. #box {
  2. width: 200px;
  3. w\idth: 180px;
  4. }

An important thing to keep in mind is the exact placement of the escape character. Explorer 5 ignores the declaration only when the escape is inside the property name and comes before any alphabetical character except of a, b, c, d, e, f. In fact, these six alphabetical characters will be interpreted as hexadecimal Unicode characters, undoing the hack. However, this hack is not valid, since the escaped property name will be interpreted as malformed.

The Star-HTML hack

This hack is used in order to deliver style rules only to Internet Explorer 6 (and lower). It relies on a wrong DOM implementation that affects Explorer since 1997. According to the specifications, the actual root element of any well-formed (X)HTML document is the html element. Instead, Explorer 6 (and lower) considers the html element as wrapped in another unknown element. The pattern is the following:

Listing 3. The Star-HTML hack

  1. * html #box {width: 200px}

Variants of this pattern are now used in order to target Internet Explorer 7. The patterns are the following:

Listing 4. Variants of the Star-HTML hack for Internet Explorer 7

  1. *:first-child + html #box {width: 200px}
  2. * + html #box {width: 200px}

The Underscore hack

This hack is used in order to deliver style rules only to Internet Explorer 6 (and lower). It relies on a different interpretation of the CSS specifications which allow browsers to use an underscore (_) or hyphen (-) as a prefix for a vendor-specific property name. However, the CSS specifications state also that such properties will never be used in a future CSS standard. In other words, these vendor-specific properties are not valid CSS property and thus this hack won’t validate. The pattern is the following:

Listing 5. The Underscore hack

  1. p {_color: red}

A variant of this pattern is now used to target also Internet Explorer 7. The pattern is the following:

Listing 6. A variant of the Underscore hack for Internet Explorer 7

  1. p {*color: red}

The Media Queries hack

This hack is used in order to deliver style rules only to the Opera browser. It relies on Opera’s support for the CSS3 Media Queries. The pattern is the following:

Listing 7. The Media Queries hack

  1. @media all and (min-width: 0px) {
  2. p {color: green}
  3. }

Opera will apply the rule contained in the at-rule block because the viewable area of the target media is usually wider than zero pixels.

CSS soup: hacks drawbacks

Hacks should be avoided for the following practical reasons:

  • Hacks are a short-term solution. They work as long as a browser supports (or doesn’t support) a particular feature or is affected by a particular bug. Browsers are changing and their CSS support is still improving. Hacks give no guarantee for the future.
  • Hacks make a style sheet more difficult to read and even more difficult to parse. For example, when we use a hack in order to target a version of Internet Explorer, what happens to other browsers? Simply put, a parser is forced to read all the nonsensical (and sometimes invalid) patterns mentioned above until it reaches the end of the style sheet. In some cases, this work may slow down the rendering process, especially when we’re dealing with large sites with a lot of external dependencies.

There are other techniques for addressing our problems with CSS, as we’ll see in the next section.

A different approach

Since the overwhelming majority of CSS problems are usually related to the CSS support of Internet Explorer, we can address such problems by using conditional comments to deliver particular styles only to Internet Explorer. Example:

Listing 8. Conditional comments for Internet Explorer

  1. <head>
  2. <link rel="stylesheet" href="styles.css" type="text/css" media="screen" />
  3. <!--[if lt IE 8]>
  4. <link rel="stylesheet" href="ie.css" type="text/css" media="screen" />
  5. <![endif]-->
  6. </head>

Since the second style sheet will be read only by Internet Explorer, we can use hacks inside it to deliver style rules to a specific version of Internet Explorer. For example:

Listing 9. Different hacks for different versions of Internet Explorer

  1. * html p {color: green} /* IE6 and lower */
  2. * + html p {color: olive} /* IE7 */

To deliver style rules to browsers other than Internet Explorer, we can use JavaScript (or a more powerful server-side language) to fulfill this task. The browser detection problem can be addressed through a simple object detection or more complicated string search routines. A simple object detection routine for the Opera browser is shown in the following example.

Listing 10. A simple object detection routine in Opera

  1. if(window.opera) {
  2. var head = document.getElementsByTagName("head")[0];
  3. var css = document.createElement("link");
  4. css.setAttribute("rel", "stylesheet");
  5. css.setAttribute("href", "opera.css");
  6. css.setAttribute("type", "text/css");
  7. css.setAttribute("media", "screen");
  8. head.appendChild(css);
  9. }

Note that in this example we’ve used the W3C DOM standard methods to attach a style sheet to the current document, since the overused document.write() method is not allowed when serving a document as application/xhtml+xml. In fact, we cannot add content to the document while the parsing process is still running.

Finally, we can also use regular expressions in order to find a particular string inside the userAgent property of the navigator object. The following example attaches a style sheet for the Firefox browser.

Listing 11. Use of regular expressions in a simple browser detection

  1. var ua = RegExp(" Firefox/").test(navigator.userAgent);
  2. if (ua) {
  3. var head = document.getElementsByTagName("head")[0];
  4. var css = document.createElement("link");
  5. css.setAttribute("rel", "stylesheet");
  6. css.setAttribute("href", "firefox.css");
  7. css.setAttribute("type", "text/css");
  8. css.setAttribute("media", "screen");
  9. head.appendChild(css);
  10. }