As you create increasingly complex style sheets, you'll sometimes wonder why a particular element on a page looks the way it does. CSS's inheritance feature, as discussed in the previous chapter, creates the possibility that any tag on a page is potentially affected by any of the tags that wrap around it. For example, the <body> tag can pass properties on to a paragraph, and a paragraph may pass its own formatting instructions on to a link within the paragraph. In other words, that link can inherit CSS properties from both the <body> and the <p> tag—essentially creating a kind of Frankenstyle that combines parts of two different CSS styles.
Then there are times when styles collide—the same CSS property is defined in multiple styles, all applying to a particular element on the page (for example, a <p> tag style in an external style sheet and another <p> tag style in an internal style sheet). When that happens, you can see some pretty weird stuff, like text that appears bright blue, even though you specifically applied a class style with the text color set to red. Fortunately, there's actually a system at work: a basic CSS mechanism known as the cascade, which governs how styles interact and which styles get precedence when there's a conflict.
This chapter deals with issues that arise when you build complex style sheets that rely on inheritance and more sophisticated types of selectors like descendent selectors (ID Selectors: Specific Page Elements). The rules are all pretty logical, but they're about as fun to master as the tax code. If that's got your spirits sagging, consider skipping the details and doing the tutorial on Tutorial: The Cascade in Action to get a taste of what the cascade is and why it matters. Or jump right to the next chapter which explores fun and visually exciting ways to format text. You can always return to this chapter later, after you've mastered the basics of CSS.
The cascade is a set of rules for determining which style properties get applied to an element. It specifies how a web browser should handle multiple styles that apply to the same tag and what to do when CSS properties conflict. Style conflicts happen in two cases: through inheritance when the same property is inherited from multiple ancestors, and when one or more styles apply to the same element (maybe a <p> tag style in an external style sheet and another <p> tag style in an internal style sheet).
As you'll read in the last chapter, CSS inheritance ensures that related elements—like all the words inside a paragraph, even those inside a link or another tag—share similar formatting. It spares you from creating specific styles for each tag on a page. But since one tag can inherit properties from any ancestor tag—a link, for example, inheriting the same font as its parent <p> tag—determining why a particular tag is formatted one way can be a bit tricky. Imagine a font family applied to the <body> tag, a font size applied to a <p> tag, and a font color applied to an <a> tag. Any <a> tag inside of a paragraph would inherit the font from the body and the size from the paragraph. In other words, the inherited styles combine to form a hybrid style.
The page shown in Figure 5-1 has three styles: one for the <body>, one for the <p> tag, and one for the <strong> tag. The CSS looks like this:
body { font-family: Verdana, Arial, Helvetica, sans-serif; } p { color: #F30; } strong { font-size: 24px; }
Figure 5-1. Thanks to inheritance, it's possible for multiple styles to affect the appearance of one tag. Here the <strong> tag has a specific color, font family, and font size, even though only a single property is applied directly to that tag. The other two formatting options were inherited from the tag's ancestors: the <body> and the <p> tags.
The <strong> tag is nested inside a paragraph, which is inside the <body> tag. That <strong> tag inherits from both of its ancestors, so it inherits the font-family property from the body and the color property from its parent paragraph. In addition, the <strong> tag has a bit of CSS applied directly to it—a 24px font size. The final appearance of the tag is a combination of all three styles. In other words, the <strong> tag appears exactly as if you'd created a style like this:
strong { font-family: Verdana, Arial, Helvetica, sans-serif; color: #F30; font-size: 24px; }
In the previous example, various inherited and applied tags smoothly combined to create an overall formatting package. But what happens when inherited CSS properties conflict? Think about a page where you've set the font color for both the body and paragraph tags. Now imagine that within one paragraph, there's a <strong> tag. Which color gets applied to text inside the <strong> tag? The color inherited from the body or the paragraph? Ladies and gentleman, we have a winner: the paragraph. That's because the web browser obeys the style that's closest to the tag in question.
In this example, any properties inherited from the <body> tag are rather generic. They apply to all tags. A style applied to a <p> tag, on the other hand, is much more narrowly defined. Its properties apply only to <p> tags and the tags inside them.
In a nutshell, if a tag doesn't have a specific style applied to it, then, in the case of any conflicts from inherited properties, the nearest ancestor wins (see Figure 5-2, number 1).
Here's one more example, just to make sure the concept sinks in. If a CSS style defining the color of text were applied to a <table> tag, and another style defining a different text color were applied to a <td> tag inside that table, then tags inside that table cell (<td>) such as a paragraph, headline, or unordered list would use the color from the <td> style, since it's the closest ancestor.
Taking the "nearest ancestor" rule to its logical conclusion, there's one style that always becomes king of the CSS family tree—any style applied directly to a given tag. Suppose a font color is set for the body, paragraph, and strong tags. The paragraph style is more specific than the body style, but the style applied to the <strong> tag is more specific than either one. It formats the <strong> tags and only the <strong> tags, overriding any conflicting properties inherited from the other tags (see Figure 5-2, number 2). In other words, properties from a style specifically applied to a tag beat out any inherited properties.
This rule explains why some inherited properties don't appear to inherit. A link inside a paragraph whose text is red still appears browser-link blue. That's because browsers have their own predefined style for the <a> tag, so an inherited text color won't apply.
Figure 5-2. Here's how web browsers figure out which properties to display when inherited properties conflict: The <em> tag in the first paragraph (1) inherits the font family and color from both the <body> tag and the paragraph. But since the body and paragraph have different fonts and colors applied to them, the <em> tag uses the font and color specified for its closest ancestor—the <p> tag. When a style applies directly to a tag—the font-family and color are specified for the <strong> tag (2)—browsers ignore conflicting inherited properties.
You can learn how to overcome preset styles for the <a> tag and change link colors to your heart's content. See Grouping links with descendent selectors.
Inheritance is one way that a tag can be affected by multiple styles. But it's also possible to have multiple styles apply directly to a given tag. For example, say you have an external style sheet with a <p> tag style and attach it to a page that has an internal style sheet that also includes a <p> tag style. And just to make things really interesting, one of the <p> tags on the page has a class style applied to it. So for that one tag, three different styles directly format it. Which style—or styles—should the browser obey?
The answer: It depends. Based on the types of styles and the order in which they're created, a browser may apply one or more of them at once. Here are a few situations in which multiple styles can apply to the same tag:
The tag has both a tag selector and a class style applied to it. For example, a tag style for the <h2> tag, a class style named .leadHeadline and this HTML: <h2 class="leadHeadline">Your Future Revealed!</h2>. Both styles apply to this <h2> tag.
The same style name appears more than once in the style sheet. There could be a group selector (Constructing Group Selectors), like .leadHeadline, .secondaryHeadline, .newsHeadline, and the class style .leadHeadline in the same style sheet. Both of these rules define how any element with a class of leadHeadline looks.
A tag has both a class and an ID style applied to it. Maybe it's an ID named #banner, a class named .news, and this HTML: <div id="banner" class="news">. Properties from both the banner and news styles apply to this <div> tag.
There's more than one style sheet containing the same style name attached to a page. The same-named styles can arrive in an external style sheet via @import or link and an internal style sheet.
There are complex selectors targeting the same tag. This situation is common when you use descendent selectors (The HTML Family Tree). For example, say you have a div tag in a page (like this: <div id="mainContent"> ), and inside the div is a paragraph with a class applied to it: <p class="byline">. The following selectors apply to this paragraph:
#mainContent p
#mainContent .byline
p.byline
.byline
If more than one style applies to a particular element, then a web browser combines the properties of all those styles, as long as they don't conflict. An example will make this concept clearer. Imagine you have a paragraph that lists the name of the web page's author, including a link to his email address. The HTML might look like this:
<p class="byline">Written by <a href="mailto:jean@cosmofarmer.com
">JeanGraine
de Pomme</a></p>
Meanwhile, the page's style sheet has three styles that format the link:
a { color: #6378df; } p a { font-weight: bold; } .byline a { text-decoration: none; }
The first style turns all <a> tags powder blue; the second style makes all <a> tags that appear inside a <p> tag bold; and the third style removes the underline from any links that appear inside an element with the byline class applied to it.
All three styles apply to that very popular <a> tag, but since none of the properties are the same, there are no conflicts between the rules. The situation is similar to the inheritance example (Inherited Styles Accumulate): the styles combine to make one überstyle containing all three properties, so this particular link appears powder blue, bold, and underline-free.
Your head will really start to ache when you realize that this particular link's formatting can also be affected by inherited properties. For example, it would inherit any font family that's applied to the paragraph. A few tools can help sort out what's going on in the cascade. (See the box on The Tiebreaker: Last Style Wins.)