Chapter 8. Cascading Style Sheets

Stylesheets are the way publishing professionals manage the overall "look" of their publications—backgrounds, fonts, colors, and so on—from a single page to huge collections of documents. Most desktop publishing software supports stylesheets, as do popular word processors, so using stylesheets for HTML documents is obvious.

For the most part, HTML focuses on content over style. Authors are encouraged to worry about providing high-quality information and leave it to the browser to worry about presentation. We strongly urge you to adopt this philosophy in your documents—don't mistake style for substance.

However, presentation is for the benefit of the reader, and even the original designers of HTML understand the interplay between style and readability—for example, through the physical style and header tags. Stylesheets extend that presentation with several additional effects, including colors, a wider selection of fonts, and even sounds so that users can better distinguish elements of your document. But most importantly, stylesheets let you control the presentation attributes for all the tags in a document—for a single document or a collection of many documents—from a single master.

In early 1996, the World Wide Web Consortium (W3C) put together a draft proposal defining Cascading Style Sheets (CSS) for HTML. This draft proposal quickly matured into a recommended standard. In mid-1998, the W3C extended the original specification to create CSS2, which includes presentation standards for a variety of media besides the familiar onscreen browser, along with several other enhancements.

The W3C continues to work on a minor version upgrade (version 2.1) and a draft of CSS3, but these are not imminent. Indeed, no current browser or web agent fully complies with the CSS2 standard. However, because we realize that eventual compliance with the W3C standard is likely, we'll cover all the components of the CSS2 standard in this chapter. As always, we'll denote clearly what is real, what is proposed, and what is actually supported.[*]

At the simplest level, a style is nothing more than a rule the browser follows to render a particular HTML or XHTML tag's contents.[*] Each tag has a number of style properties associated with it, whose values define how that tag is rendered by the browser. A rule defines a specific value for one or more properties of a tag. For example, most tags can have a color property, the value of which defines the color in which the modern GUI browser should display the contents of the tag. Other properties include fonts, line spacing, margins, borders, sound volume, and voice, which we describe in detail later in this chapter.

There are three ways to attach a style to a tag: inline, on the document level, or through the use of an external stylesheet. You may use one or more stylesheets for your documents. The browser either merges the style definitions from each style or redefines the style characteristic for a tag's contents. Styles from these various sources are applied to your document, combining and defining style properties that cascade from external stylesheets through local document styles, and ending with inline styles. This cascade of properties and style rules gives rise to the standard's name: Cascading Style Sheets.

We cover the syntactic basics of the three stylesheet techniques here. We delve more deeply into the appropriate use of inline, document-level, and external stylesheets at the end of this chapter.

The real power of stylesheets becomes more evident when you place a list of presentation rules at the beginning of your HTML or XHTML document. Placed within the <head> and enclosed within their own <style> and </style> tags, document-level stylesheets affect all the same tags within that document, except for tags that contain overriding inline style attributes.[*]

Everything between the <style> and </style> tags is considered part of the style rules that the browser is to apply when rendering the document. Actually, the contents of the <style> tag are not HTML or XHTML and are not bound by the normal rules for markup content. The <style> tag, in effect, lets you insert foreign content into your document that the browser uses to format your tags.

For example, a styles-conscious browser displays the contents of all <h1> tags as blue, italic text in an HTML document that has the following document-level stylesheet definition in its head:

<head>
<title>All True Blue</title>
<style type="text/css">
  <!--
  /* make all level-1 headers blue in italics */
  h1 {color: blue; font-style: italic}
  -->
</style>
</head>
<body>
<h1>I'm so bluuuuoooo!</h1>
...
<h1>I am ba-loooooo, tooooo!</h1>

HTML and XHTML documents can wind up in the strangest places these days, such as on cellular phones. To help the browser figure out the best way to render your documents, include the media attribute within the <style> tag. The value of this attribute is the document's intended medium, although it doesn't preclude rendering by other media. The default value is screen (computer display). Other values include tty (text only), tv (television), projection (theaters), handheld (PDAs and cell phones), print (ink on paper), braille (tactile devices), embossed (Braille printers), aural (audio; speech synthesis, for instance), and all (many different types of media).

If you want to explicitly list several types of media, instead of specifying all, use a quote-enclosed, comma-separated list of media types as the value of the media attribute. For example:

<style type="text/css" media="screen,print">

tells the browser that your document contains CSS both for printing and for computer displays.

Be careful specifying media, because the browser cannot apply the styles you define unless the document is being rendered on one of your specified media. Thus, the browser would not apply our example set of styles designed for media="screen,print" if the user is, for instance, connected to the Web with a handheld computer.

How do you create different style definitions for different media without creating multiple copies of your document? The CSS2 standard lets you define media-specific stylesheets through its extension to the @import at-rule and through the @media at-rule, which we describe in section 8.1.5 later in this chapter.

You can also place style definitions into a separate document (a text file with the Multipurpose Internet Mail Extension, or MIME, type of text/css) and import this external stylesheet into your document. Use the same stylesheet for other documents in your collection, too, even entire collections of documents, to achieve a consistent look and feel. Because an external stylesheet is a separate file and the browser loads it over the network, you can store it anywhere, reuse it often, and even use others' stylesheets.

For example, suppose we create a file named gen_styles.css containing the following style rule:

h1 {color: blue; font-style: italic}

For each and every one of the documents in our collections, we can tell the browser to read the contents of the gen_styles.css file, which in turn colors all the <h1> tag contents blue and renders the text in italic. Of course, that is true only if the user's machine is capable of these style tricks, she's using a styles-conscious browser, and the style isn't overridden by a document-level or inline style definition.

You can load external stylesheets into your document in two different ways: by linking them or by importing them.

Besides the media attribute for the <style> tag, the CSS2 standard has two other features that let you apply different stylesheets, depending on the agent or device that renders your document. This way, for instance, you can have one style or whole stylesheet take effect when your document gets rendered on a computer screen and another set of styles for when the contents get punched out on a Braille printer. And what about those cell phones that access the Web?

Like the media attribute for the <style> tag that affects the entire stylesheet, you can specify whether the user's document processor loads and uses an imported stylesheet. Do that by adding a media-type keyword or a series of comma-separated keywords to the end of the @import at-rule. For instance, the following example lets the user agent decide whether to import and use the speech-synthesis stylesheet or a common PC display and print stylesheet, if it is able to render the specified media types:

@import url(http://www.kumquats.com/styles/visual_styles.css) screen,print;
@import "http://www.kumquats.com/styles/speech_styles.css" aural;

The @import CSS2 media types are the same as those for the <style> tag's media attribute, including all, aural, braille, embossed, handheld, print, projection, screen, tty, and tv.

Another CSS2 way to select media is through the explicit @media at-rule, which lets you include media-specific rules within the same stylesheet, either at the document level or in an external stylesheet. At the document level, as with @import, the @media at-rule must appear within the contents of the <style> tag. The at-rules may not appear within another rule. Unlike @import, @media may appear subsequent to other style rules, and its style-rule contents override previous rules according to the cascading standard.

The contents of @media include one or more comma-separated media-type keywords followed by a curly brace ({})-enclosed set of style rules. For example:

body {background: white}
@media tv, projection     {
    body {background: yellow}
    }

The yellow attribute to the @media at-rule causes the body's background color to display yellow, rather than the default white set in the general style rule, when the document is rendered on a television or projection screen (as specified by the tv and projection attributes).

At first glance, it may appear that linked and imported stylesheets are equivalent, using different syntax for the same functionality. This is true if you use just one <link> tag in your document. However, special CSS2-standard rules come into play if you include two or more <link> tags within a single document.

With one <link> tag, the browser should load the styles in the referenced stylesheet and format the document accordingly, with any document-level and inline styles overriding the external definitions. With two or more <link> tags, the browser should present the user with a list of all the linked stylesheets. The user then selects one of the linked sheets, which the browser loads and uses to format the document; the other linked stylesheets get ignored.

On the other hand, the styles-conscious browser merges, as opposed to separating, multiple @imported stylesheets to form a single set of style rules for your document. The last imported stylesheet takes precedence if there are duplicate definitions among the stylesheets. Hence, if the external gen_styles.css stylesheet specification first tells the browser to make <h1> contents blue and italic, and then a later spec_styles.css tells the browser to make <h1> text red, the <h1> tag contents appear red and italic. And if we later define another color—say, yellow—for <h1> tags in a document-level style definition, the <h1> tags are all yellow and italic. Cascading effects. See?

In practice, the popular browsers treat linked stylesheets just like imported ones by cascading their effects. The browsers do not currently let you choose from among linked choices. Imported styles override linked external styles, just as the document-level and inline styles override external style definitions. To bring this all together, consider this example:

<html>
<head>
<link rel=stylesheet href=sheet1.css type=text/css>
<link rel=stylesheet href=sheet2.css type=text/css>
<style>
<!--
  @import url(sheet3.css);
  @import url(sheet4.css);
-->
</style>
</head>

Using the CSS2 model, the browser should prompt the user to choose sheet1.css or sheet2.css. It should then load the selected sheet, followed by sheet3.css and sheet4.css. Duplicate styles defined in sheet3.css or sheet4.css, and in any inline styles, override styles defined in the selected sheet. In practice, the popular browsers cascade the stylesheet rules as defined in the example order sheet1 through sheet4.

Comments are welcome inside the <style> tag and in external stylesheets, but treat them differently than HTML comments: stylesheets aren't HTML. Rather, enclose style comments between /* and */ markers, as we did in the example in section 8.1.2, earlier in this chapter. (Those of you who are familiar with the C programming language will recognize these comment markings.) Use this comment syntax for both document-level and external stylesheets. Comments cannot be nested.

We recommend documenting your styles whenever possible, especially in external stylesheets. Whenever the possibility exists that other authors may use your styles, comments make it much easier to understand your styles.

You may import multiple external stylesheets and combine them with document-level and inline style effects in many different ways. Their effects cascade (hence the name, of course). You may specify the font type for our example <h1> tag, for instance, in an external style definition, whereas its color may come from a document-level stylesheet.

Stylesheet effects are not cumulative, however: of the many styles that may define different values for the same property—colors for the contents of our example tag, for instance—the one that takes precedence can be found by following these rules, listed here in order:

Sort by origin

A style-defined "closer" to a tag takes precedence over a more "distant" style; an inline style takes precedence over a document-level style, which takes precedence over the effects of an external style.

If more than one applicable style exists, sort by class

A property defined as a class of a tag (see section 8.3, later in this chapter) takes precedence over a property defined for the tag in general.

If multiple styles still exist, sort by specificity

The properties for a more specific contextual style (see section 8.2.3, later in this chapter) take precedence over properties defined for a less specific context.

If multiple styles still exist, sort by order

The property specified latest takes precedence.

The relationship between style properties and conventional tag attributes is almost impossible to predict. For instance, stylesheet-dictated background and foreground colors—whether defined externally, at the document level, or inline—override the various color attributes that may appear within a tag. But the align attribute of an inline image usually takes precedence over a style-dictated alignment.

Myriad style and tag presentation-attribute combinations exist. You need a crystal ball to predict which combination wins and which loses the precedence battle. The rules of redundancy and style-versus-attribute precedence are elucidated in the W3C CSS2 standard, but no clear pattern of precedence is implemented in the styles-conscious browsers. This is particularly unfortunate because there will be an extended period, perhaps several more years, in which users may or may not use styles-conscious browsers. Authors must implement both styles and nonstyle presentation controls to achieve the same effects.

Nonetheless, our recommendation is to run—as fast as you can—from one-shot, inline, localized kinds of presentation effects such as those afforded by the <font> tag and color attribute. They have served their temporary purpose; it's now time to bring consistency (without the pain!) back into your document presentation. Use styles.



[*] In the fall of 2000, work began on CSS3. As CSS3 is still under construction and browsers have not yet even become fully compliant with CSS2, we focus on CSS2 throughout this chapter.

[*] We explicitly avoided the term display here because it connotes visual presentation, whereas the CSS2 standard works hard to suggest many different ways of presenting the tagged contents of a document.

[*] XHTML-based document-level stylesheets are specially enclosed in CDATA sections of your documents. See section 16.3.7 in Chapter 16 for details.