The Monster
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.
How Styles Cascade
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).
Inherited Styles Accumulate
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; }
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;
}
Nearest Ancestor Wins
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.
The Directly Applied Style Wins
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.
One Tag, Many Styles
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 (page 56), 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 (page 57). 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 (page 92): the styles combine to make one überstyle containing
all three properties, so this particular link appears powder blue, bold, and
underline-free.
Note: 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 page 98.)
Specificity: Which Style Wins
The previous example is pretty straightforward. But what if the three styles listed
on page 92 each had a different font specified for the font-family property? Which
of the three fonts would a web browser pay attention to?
As you know if you’ve been reading carefully so far, the cascade provides a set of
rules that helps a web browser sort out any property conflicts; namely, properties
from the most specific style win. But as with the styles listed on page 92, sometimes it’s
not clear which style is most specific. Thankfully, CSS provides a formula for determining
a style’s specificity that’s based on a value assigned to the style’s selector—a
tag selector, class selector, ID selector, and so on. Here’s how the system works:
• A tag selector is worth 1 point.
• A class selector is worth 10 points.
• An ID selector is worth 100 points.
• An inline style (page 39) is worth 1,000 points.
Note: The math involved in calculating specificity is actually a bit more complicated than described here.
But this formula works in all but the weirdest cases. To read how web browsers actually calculate specificity
visit www.w3.org/TR/CSS21/cascade.html#specificity.
The bigger the number, the greater the specificity. So say you create the following
three styles:
• a tag style for the <img> tag ( specificity = 1)
• a class style named .highlight (specificity = 10)
• an ID style named #logo (specificity = 100)
Then, say your web page has this HTML: <img id="logo" class="highlight"
src="logo.gif" />. If you define the same property—such as the border property—
in all three styles, then the value from the ID style (#logo) always wins out.
Since descendent selectors are composed of several selectors—#content p, or h2
strong, for example—the math gets a bit more complicated. The specificity of a
descendent selector is the total value of all of the selectors listed
The Tiebreaker: Last Style Wins
It’s possible for two styles with conflicting properties to have the same specificity.
(“Oh brother, when will it end?” Soon, comrade, soon. The tutorial is coming up.)
A specificity tie can occur when you have the same selector defined in two locations.
You may have a <p> tag selector defined in an internal style sheet and an
external style sheet. Or two different styles may simply have equal specificity values.
In case of a tie, the style appearing last in the style sheet wins.
Here’s a tricky example using the following HTML:
<p class="byline">Written by <a class="email" href="mailto:jean@cosmofarmer.
com">Jean Graine de Pomme</a></p>
In the style sheet for the page containing the above paragraph and link, you have
two styles:
p .email { color: blue; }
.byline a { color: red; }
Both styles have a specificity of 11 (10 for a class name and 1 for a tag selector) and
both apply to the <a> tag. The two styles are tied. Which color does the browser
use to color the link in the above paragraph? Answer: Red, since it’s the second
(and last) style in the sheet.
Now suppose that the style sheet looked like this instead:
p .email { color: blue; }
.byline a { color: red; }
In this case, the link would be red. Since .byline a appears after p .email in the style
sheet, its properties win out.
What happens if you’ve got conflicting rules in an external and an internal style
sheet? In that case, the placement of your style sheets (within your HTML file)
becomes very important. If you first add an internal style sheet using the <style> tag
(page 34) and then attach an external style sheet farther down in the HTML using the
<link> tag (page 36), then the style from the external style sheet wins. (In effect, it’s
the same principle at work that you just finished reading about: The style appearing
last wins.) The bottom line: Be consistent in how you place external style sheets. It’s
best to list any external style sheets first, and then include any internal styles.
Note: Any external style sheets attached with the @import rule have to appear before internal styles
within a <style> tag. See page 34 for more information on external and internal style sheets.
Controlling the Cascade
As you can see, the more CSS styles you create, the greater the potential for formatting
snafus. For example, you may create a class style specifying a particular
font and font size, but when you apply the style to a paragraph, nothing happens!
This kind of problem is usually related to the cascade. Even though you may think
that directly applying a class to a tag should apply the class’s formatting properties,
it may not if there’s a style with greater specificity.
You have a couple of options for dealing with this kind of problem. First, you can
use !important (as described in the box above) to make sure a property always
applies. The !important approach is a bit heavy handed, though, since it’s hard to
predict that you’ll never, ever, want to overrule an !important property someday.
Read on for two other cascade-tweaking solutions.
Changing the Specificity
The top picture in Figure 5-4 is an example of a specific tag style losing out in the
cascade game. Fortunately, most of the time, you can easily change the specificity
of one of the conflicting styles and save !important for real emergencies. In
Figure 5-4 (top), two styles format the first paragraph. The class style—.intro—
isn’t as specific as the #sidebar p style, so .intro’s properties don’t get applied to the
paragraph. To increase the specificity of the class, add the ID name to the style:
#sidebar .intro.
Note: If you’re into math, the #sidebar p style has a specificity of 101 (100 for the ID, and 1 for the tag selector), while the .intro style has a specificity of 10 (10 points for a class selector). Since 101 is greater than 10, #sidebar p takes precedence. Changing .intro to #sidebar .intro changes its specificity to 110.
Selective Overriding
You can also fine-tune your design by selectively overriding styles on certain pages.
Say you’ve created an external style sheet named global.css that you’ve attached to
each page in your site. This file contains the general look and feel for your site—
the font and color of <h1> tags, how form elements should look, and so on. But
maybe on your home page, you want the <h1> tag to look slightly different than
the rest of the site—bolder and bigger, perhaps. Or the paragraph text should be
smaller on the home page, so you can wedge in more information. In other words,
you still want to use most of the styles from the global.css file, but you simply want One approach is to simply create an internal style sheet listing the styles that you
want to override a few properties for some of the tags (<h1>, <p>, and so on)..
Maybe the global.css file has the following rule:
h1 {
font-family: Arial, Helvetica, sans-serif;
font-size: 24px;
color: #000;
}
You want the <h1> tag on the home page to be bigger and red. So just add the following
style in an internal style sheet on the home page:
h1 {
font-size: 36px;
color: red;
}
In this case, the <h1> tag on the home page would use the font Arial (from the
external style sheet) but would be red and 36 pixels tall (from the internal style).
Tip: Make sure you attach the external style sheet before the internal style sheet in the <head> section of
the HTML. This ensures that the styles from the internal style sheet win out in cases where the specificity
of two styles are the same, as explained on page 96.
Another approach would be to create one more external style sheet—home.css for
example—that you attach to the home page in addition to the global.css style sheet.
The home.css file would contain the style names and properties that you want to
overrule from the global.css file. For this to work, you need to make sure the home.
css file appears after the global.css file in the HTML, like so:
<link rel="stylesheet" type="text/css" href="css/global.css" />
<link rel="stylesheet" type="text/css" href="css/home.css" />
Tip: Another way to fine-tune designs on a page-by-page basis is to use different ID names for the <body> tag of different types of pages—for example #review, #story, #home—and then create descendent selectors to change the way tags on these types of pages look.
Starting with a Clean Slate
Browsers apply their own styles to tags: for example,
<h1> tags are bigger than <h2> tags, and both are bold, while paragraph text is
smaller and isn’t bold; links are blue and underlined; and bulleted lists are
indented. There’s nothing in the HTML standard that defines any of this formatting:
Web browsers just add this formatting to make basic HTML more readable.
However, even though browsers treat all tags roughly the same, they don’t treat
them identically.