Inheritance: Friend and Foe

Web Review
March 1999

One of the most fundamental aspects of CSS is the concept of inheritance. This refers to the way in which a style is passed from an element to its children, so that styles appear to be consistent. This mechanism is indispensible, but it can also be a source of confusion and annoyance-- especially if you aren't careful. We'll take a quick look at how inheritance works, and why some properties are inherited while others are not. Then we'll touch on a few ways in which inheritance can actually be an obstacle, albeit one which is easily overcome.

The Basics

First, a quick review of the terms we'll using. A child element is an element which is part of another, and a parent element is an element which has children. For example, given the markup in Figure 1, the <P> element is a child of the <BODY> element, and the <A> and <STRONG> elements are children of the paragraph. Conversely, the paragraph is the parent to the <A> and <STRONG> elements, and the <BODY> is the parent of the paragraph.

<P>
This paragraph contains <EM>emphasized text</EM> and 
a hyperlink created with <A HREF="http://style.webreview.com/">
an anchor tag</A>.
</P>
Figure 1. Example markup

Inheritance, then, is the process by which a style is passed from a parent to a child. For example, if you define a paragraph to be purple in color, then it stands to reason that the text in the paragraph should all be purple. It wouldn't look right if plan text were purple, and <EM> text in the middle of that paragraph were not purple. However, without inheritance, that's exactly what you'd have. Since color is an inherited property, its values are passed from a parent element to its children. Figure 2 shows the difference between the two possibilities-- the first one is the correct way, and the second is a hypothetical screenshot from an evil parallel universe where CSS has no inheritance.


Figure 2. Text color with and without inheritance

All right, so we know how inheritance works. Not all properties are inherited, however. As an example, most of the box properties (margins, padding, and borders) are not inherited. This only makes sense, since if they were, then elements inside an element with a border would themselves have borders. Figure 3 shows the difference; again, the first image shows the Right Way, and the second is the Wrong Way.


Figure 3. Borders without and with inheritance

(For a complete list of CSS1 properties which are not inherited, see the table at the end of this article.)

Oops! Inheritance!

Great stuff, right? How could inheritance possibly be bad?

As it happens, there are circumstances in which inheritance can be a little-- confusing. It isn't really bad, of course, but it can bite you in unexpected ways. One way is when a style is inherited when you don't expect it.

A few months back, I got e-mail from a developer who had a big problem: his boldface tags were working fine in one browser, but not the other. His markup was clean, there was nothing wrong with the tags, and the styles all checked out as correct. There was no apparent reason why the boldface would just refuse to work in one browser. So he asked me to take a look.

It took me a few minutes, but eventually I figured it out:

BODY {font-weight: normal;}

What was happening was that in one browser, this weight value of normal was inheriting into the <B> tag, thus suppressing the boldface style. The fix was simple enough:

BODY {font-weight: normal;}
B {font-weight: bold;}

That was all it took. This works because inheritance always loses to a direct style assignment. If an element (such as <B>) inherits a value (such as font-weight: normal), but it has a more direct rule associated with it (see above), then the assigned rule overrides whatever value was inherited.

Let's take that a step further. Remember the "wrong" example in Figure 1? Let's assume that you actually want your paragraph to look like that, with the <EM> and other elements in black, not purple. In order to do that, you would need the following styles:

P {color: purple;}
EM, STRONG {color: black;}

Figure 4. Overriding inheritance

Instead of inheriting the value purple, the <EM> and STRONG element use the declared value of black instead.

Inheritance Tax

Now, let's go back to the boldface problem. It doesn't really make sense that a browser would inherit a style into an element which would override its usual behavior, right?

As usual-- yes and no. From a CSS point of view, elements don't have "usual behavior." They only have whatever styles are specified. The reason that browser overrode the font weight of the <B> element is that for some reason, it didn't have a predefined CSS rule regarding the weight of that particular element.

This isn't really a good thing, obviously. There are some elements which should have a small set of pre-defined styles. <B> is one of them, as we've seen. On the other hand, there is such a thing as taking it too far. Inheritance into tables is one area of possible trouble.

As you may know, some styles just don't inherit into tables. For example, try creating a document in which the color for the body is green and monospace, and inside that document, include a table with some text in it. Now, load that file into Explorer 4.x for Windows, or Navigator 4.x on any platform. Odds are, you'll see green body text, but black text in another type of font inside the table.

This could be written off as a simple breakdown in the chain of inheritance, and that could well be the case. But another explanation is that the browser already has a predefined style for the color of the text, and at least one or two developers have claimed to me that this is the case. In fact, some browsers appear to have preset styles for the font, size, and color of text inside tables.

This is a major problem, because your styles combined with the browser's built-in styles could come out something like this, assuming your browser's preferences are set to use black serif text for document display:

BODY {color: green; font-family: monospace;}
TABLE {color: black; font-family: serif;}

The best fix would be for browsers to not assign these kinds of styles to tables. Failing that, however, you can beat the problem like this:

BODY, TABLE, TH, TD {color: green; font-family: monospace;}

Now, you have specific styles which will override the browser's built-in styles, and text inside of tables will be consistent with the text in the rest of your document.

Trickling Down

Despite the problems one can encounter, we're definitely a lot better off with inheritance than without it. Over time, we can hope that browsers become more intelligent about how their built-in styles should be written, and we all can worry a little less about trying to cover every last detail of the document's appearance.

On the other hand, this is a good lesson to learn: the less you assume about how a document will be displayed, and the more comprehensive your styles are, the less likely you'll be to trip over problems like those explained in this article. Just becuase you think the <STRONG> element should be boldfaced, that doesn't necessarily make it so. If you really think that it should be boldfaced in your documents, then make sure you declare that in your stylesheets. Otherwise, a browser might come along with different assumptions, and people using that browser won't see any boldfaced text at all.

Figure 5. CSS1 properties which are NOT inherited
background-color
background-image
background-repeat
background-attachment
background-position
background
text-decoration
vertical-align
margin-top
margin-right
margin-bottom
margin-left
margin
padding-top
padding-right
padding-bottom
padding-left
padding
border-top-width
border-right-width
border-bottom-width
border-left-width
border-width
border-color
border-style
border-top
border-right
border-bottom
border-left
border
width
height
float
clear
display