Untold Mysteries of CSS
Date: Dec 23, 2004
Three CSS features you might not know about include the universal selector, !important keywords, and multi-classes. Sure, if you're knee-deep in CSS and standards-based design, you've probably seen at least one of these techniques, but the broader developer audience is sure to find these under-described aspects of CSS extremely useful, too.
Universal Selector
The universal selector is represented by the asterisk: *. It can function as a wildcard, just as you'd expect. Here, I've applied the universal selector to a style declaration:
* {border: 1px solid orange;}
Every element in the (X)HTML document is now styled with a one-pixel solid orange border (see Figure 1).
Figure 1 Notice that all the elements are styled, including the html element (the border surrounding the viewport) and the body element.
The universal selector can be combined with other selectors. Doing so causes a jump across a generation and passes styles only to descendent elements beyond any child elements. Surely many parents have occasionally wanted to select only grandchildren and beyond, but write the children out of the equation!
Consider this rule:
#content * p {border: 1px solid orange;}
No child paragraph elements of the #content div will be selected, but any descendents further on down the line will be selected.
NOTE
Most all compliant browsers expect a space between the universal selector and any other selector.
Check out the following HTML:
<div id="content"> <h1>The Black Cat</h1> <h2>By Edgar Allen Poe</h2> <p>I married early, and was happy to find in my wife a disposition not uncongenial with my own. Observing my partiality for domestic pets, she lost no opportunity of procuring those of the <a href="http://vig.prenhall.com/">most</a> agreeable kind. We had birds, gold fish, a fine dog, rabbits, a small monkey, and a cat.</p> <div id="nested1"> <p>Here's a grandchild paragraph, which is in fact selected.</p> <div id="nested2"> <p>Here's a great-grandchild paragraph, which is in fact selected.</p> </div> </div> <p>This latter was a <a href="http://vig.prenhall.com/">remarkably</a> large and beautiful animal, entirely black, and sagacious to an astonishing degree. In speaking of his intelligence, my wife, who at heart was not a little tinctured with superstition, made frequent allusion to the ancient popular notion, which regarded all black cats as witches in disguise. Not that she was ever serious upon this point - and I mention the matter at all for no better reason than that it happens, just now, to be remembered.</p> <div id="nested3"> <p>Here's a grandchild paragraph, which is in fact selected.</p> </div> <p>Pluto - this was the cat's name - was my <a href="http://vig.prenhall.com/">favorite</a> pet and playmate. I alone fed him, and he attended me wherever I went about the house. It was even with difficulty that I could prevent him from following me through the streets.</p> </div>
Figure 2 shows the results.
Figure 2 Only descendants beyond child elements are styled.
The universal selector is rarely used as intended, in part because it's unknown to many folksespecially those accustomed to working with visual editors rather than hand-coding. Its appropriate use is also limited to universal and descendant styles, or in diagnostic testing by developers.
What's more, Internet Explorer has a bug where the universal selector is concerned, and it's not just IE 6.0 for Windows, either. Macintosh 5.0, 5.15, and 5.21; and Windows 5.0, 5.5, and 6.0 all have the bug present. That's in both quirks and standards mode.
The bug, referred to as the Star HTML Selector Bug, causes IE to misinterpret the universal selector (see Table 1).
Table 1 Browser Interpretations as Applied to html and body Elements
Selector |
In IE, Interpreted as |
Correct Interpretation |
* html |
html |
Matches to no element, because html is root and can never be a grandchild element |
* * body |
* body |
Matches to no element because body, although a child of html, can never be a grandchild element |
* html body | html body | Matches no element |
So here we have a case in which these selectors, although valid syntactically, are connected to no elements whatsoever in browsers that correctly interpret them. In IE, the selectors are improperly interpreted, and IE will apply a style!
Of course, any time syntax is misinterpreted by a browser puts that syntax in perfect line to be exploited for CSS hacking because using them will filter styles to those versions of IE but not to any other contemporary browsers.
!Important or Not?
!important has been around since CSS1. Contrary to common programming syntax, it doesn't mean not important.
!important is meant to provide a balance of power between author and user styles. Author style sheets are those styles designated by the designer or developer. User style sheets are those styles authored by a user and applied via the browser.
User styles are important for accessibility purposes. A user with a vision problem can apply a style sheet via the browser that forces larger fonts and high contrast for more comfortable reading. !important ensures the user style will trump the author style.
So, if we have an author style sheet:
h1 {color: red;}
and a user style sheet:
h1 {color: blue; !important}
applied to the same document, the user style trumps the author style (see Figure 3).
Figure 3 The h1 element is blue due to the !important rule within the user's style sheet.
That the user style will override the author style is true even if there's an !important in an author's rule. If the author style sheet were the following, the user's !important style will still dominate:
h1 {color: red; !important}
NOTE
Here's a bit of historic curiosity. In CSS1, author !important rules took precedence over user !important rules. In CSS 2.x, it's the opposite.
Another oddity: !important is a unique syntactic construct in CSS. The specification refers to !important as being two unique keywords: ! and important. An !important declaration is any declaration with the ! and important keywords included, and an !important rule is any complete CSS rule with the ! and important keywords included within it.
Finally, IE misinterprets the !important keywords, but somehow you knew that was coming!
Multiple Classes
Multiple classes is the technique of applying two or more classes for a single element. The class values are placed in the (X)HTML and are space-separated values:
<div class="module widget"> </div>
The classed element will then interpret all classes:
.module {width: 200px; border: 1px dashed #000; padding: 10px;} .widget {font: 12px Arial, Helvetica, sans-serif; color: #333;}
Figure 4 shows the results.
Figure 4 Applying multiple classes to an element.
Multi-classes are useful in a range of situations. One situation in particular is portal sites, in which common modules that can have a number of style sets applied to them are in use. This way, you can have a class for the module and then add classes as needed to address styles for that module. You can also use them, as with the universal selector and !important keywords, for diagnostic purposes when working on styling complex documents.
Of course, just as the overuse of classes themselves is not recommended, the overuse of multi-classes is to be avoided. The humorous term "classitis" refers to the overuse of classes in generalideally, you're tapping into inheritance, the cascade, and descendant selectors to remove as much from the markup and into the CSS as possible.
Mysteries Revealed
I always joke that with CSS, there's more than one way to skin a cat. There's an explicit truth in the humor there, in that CSS does allow us numerous means to address a range of needs. The universal selector, !important keywords, and use of multi-classes can all be put to use to assist with such needs as diagnostics during development, savvy global styling, out-and-out hacks, better design flexibility, and accessibility.