3.2 Inheritance

Previous Page Table of Contents Next Page

3.2 Inheritance

As important as specificity may be to understanding how declarations are applied to a document, another key concept is that of inheritance. Inheritance is the mechanism by which styles are applied not only to a specified element, but also to its descendants. If a color is applied to an h1 element, for example, then that color is applied to all text in the h1, even the text enclosed within child elements of that h1:

h1 {color: gray;}

<h1>Meerkat <em>Central</em></h1>

Both the ordinary h1 text and the em text are colored gray because the em element inherits the value of color. If property values could not be inherited by descendant elements, the em text would be black, not gray, and you'd have to color that element separately.

Inheritance also works well with unordered lists. Let's say you apply a style of color: gray; for ul elements:

ul {color: gray;}

You expect that a style that is applied to a ul will also be applied to its list items, and to any content of those list items. Thanks to inheritance, that's exactly what happens, as Figure 3-3 demonstrates.

Figure 3-3. Inheritance of styles

It's easier to see how inheritance works by turning to a tree diagram of a document. Figure 3-4 shows the tree diagram for a very simple document containing two lists: one unordered and the other ordered.

Figure 3-4. A simple tree diagram

When the declaration color: gray; is applied to the ul element, that element takes on that declaration. The value is then propagated down the tree to the descendant elements and continues on until there are no more descendants to inherit the value. Values are never propagated upward; that is, an element never passes values up to its ancestors.

3.2 Inheritance

There is an exception to the upward propagation rule in HTML: background styles applied to the body element can be passed to the html element, which is the document's root element and therefore defines its canvas.

Inheritance is one of those things about CSS that is so basic that you almost never think about it unless you have to. However, you should still keep a few things in mind.

First, note that some properties are not inheritedŚgenerally as a result of simple common sense. For example, the property border (which is used to set borders on elements) does not inherit. A quick glance at Figure 3-5 will reveal why this is the case. Were borders inherited, documents would become much more cluttered unless the author took the extra effort to turn off the inherited borders.

Figure 3-5. Why borders aren't inherited

As it happens, most of the box-model propertiesŚincluding margins, padding, backgrounds, and bordersŚare not inherited for the same reason. After all, you wouldn't want all of the links in a paragraph to inherit a 30-pixel left margin from their parent element!

Inherit the Bugs

Thanks to problems in various browser implementations, an author cannot rely on inheritance to operate as expected in all circumstances. For example, Navigator 4 (and, to a lesser extent, Explorer 4 and 5) does not inherit styles into tables. Thus, the following rule would result in a document with smaller text everywhere outside of tables:

body {font-size: 0.8em;}

This is not correct behavior under CSS, but it does exist, so authors have historically resorted to tricks such as:

body, table, th, td {font-size: 0.8em;}

This is more likely, although still not certain, to achieve the desired effect in buggy browsers.

Unfortunately, the above "fix" leads to an even worse problem in browsers that do implement inheritance correctly, such as IE6/Win, IE5/Mac, Netscape 6+, and others. In those browsers, you will end up with text inside a table cell that is 41% the size of the user's default font size setting. It is often more dangerous to attempt to work around inheritance bugs in old browsers than it is to write correct CSS for updated browsers.

In terms of specificity, inherited values have no specificity at all, not even zero specificity. This seems like an academic distinction until you work through the consequences of the lack of inherited specificity. Consider the following rules and markup fragment and compare them to the result shown in Figure 3-6:

* {color: gray;}

h1#page-title {color: black;}

<h1 id="page-title">Meerkat <em>Central</em></h1>


Welcome to the best place on the web for meerkat information!

Figure 3-6. Zero specificity defeats no specificity

Since the universal selector applies to all elements and has zero specificity, its color declaration's value of gray wins out over the inherited value of black, which has no specificity at all. Therefore, the em element is rendered gray instead of black.

This example vividly illustrates one of the potential problems of using the universal selector indiscriminately. Because it can match any element, the universal selector often has the effect of short-circuiting inheritance. This can be worked around, but it's often more sensible to avoid the problem in the first place by not using the universal selector indiscriminately.

The complete lack of specificity for inherited values is not a trivial point. For example, assume that a style sheet has been written such that all text in a "toolbar" is to be white on black:

#toolbar {color: white; background: black;}

This will work as long as the element with an id of toolbar contains nothing but plain text. If, however, the text within this element is all hyperlinks (a elements), then the user agent's styles for hyperlinks will take over. In a web browser, this means they'll likely be colored blue, since the browser's style sheet probably contains an entry like this:

a:link {color: blue;}

In order to overcome this problem, you would need to declare:

#toolbar {color: white; background: black;}

#toolbar a:link {color: white;}

By targeting the rule directly to the a elements within the toolbar, you'll get the result shown in Figure 3-7.

Figure 3-7. Directly assigning styles to the relevant elements
    Previous Page Table of Contents Next Page
    © 2000- NIV