While CSS is a field of endeavor all its own, we'll get started with some foundations.
Cascading Style Sheets (CSS) is a recommendation developed by the World Wide Web Consortium (W3C). It originated in 1994 when Håkon Wium Lee, working at CERN (the birthplace of HTML), published a paper titled Cascading HTML Style Sheets. It was a bold move at the right time. By then, the Web was four years old and growing quickly, yet there was still no consensus for a standard style description language. The architects of HTML knew that the language was in danger of becoming a style description language if something like CSS wasn't adopted soon.
The goal was to create a simple yet expressive language that could combine style descriptions from different sources. Another style description language, DSSSL, was already being used to format SGML documents. Though very powerful, DSSSL was too big and complex to be practical for the Web. It is a full programming language, capable of more precision and logical expression than CSS, which is a simple language, focused on the basic needs of small documents.
While other stylesheet languages existed when CSS was proposed, none offered the ability to combine multiple sources into one style description set. CSS makes the Web truly accessible and flexible by allowing a reader to override the author's styles to adapt a document to the reader's particular requirements and applications.
The W3C put forward the first CSS recommendation (later called CSS1) in 1996. A short time later, a W3C working group formed around the subject of "Cascading Style Sheets and Formatting Properties" to add missing functionality. Their recommendation, CSS2, increased the language's properties from around 50 to more than 120 when it was released in 1998. It also added concepts like generated text, selection by attribute, and media other than screen display. CSS3 is still a work in progress.
Below is a sample CSS stylesheet:
/* A simple example */ addressbook { display-type: block; font-family: sans-serif; font-size: 12pt; background-color: white; color: blue; } entry { display-type: block; border: thin solid black; padding: 5em; margin: 5em; } name, phone, email, address { display-type: block; margin-top: 2em; margin-bottom: 2em; }
This stylesheet has three rules. The first matches any addressbook element. The name to the left of the open bracket is a selector, which tells the processor what element this rule matches. The items inside the brackets are the property declaration, a list of properties to apply.
The syntax for a CSS rule is shown in Figure 5-6. It consists of a selector (1) for matching elements and a declaration (2) for describing styles. The declaration is a list of name-value assignments (3), in which each style property (4) is assigned to a value (5) with a colon (:) separator.
CSS also has a syntax for comments. Anything inside a comment is ignored by the processor. The start delimiter is /* and the end delimiter is */. A comment can span multiple lines and may be used to enclose CSS rules to remove them from consideration:
/* this part will be ignored gurble { color: red } burgle { color: blue; font-size: 12pt; } */
Whitespace is generally ignored and provides a nice way to make stylesheets more readable. The exception is when spaces act as delimiters in lists. Some properties take multiple arguments separated with spaces like border below:
sidebar { border: thin solid black }
Let's look more closely at this rule:
addressbook { display-type: block; font-family: sans-serif; font-size: 12pt; background-color: white; color: blue; }
Qualitatively, this rule is like saying, "for every addressbook element, display it like a block, set the font family to any sans serif typeface with size 12 points, set the background color to white and make the foreground (text) blue." Whenever the CSS processor encounters an addressbook element, it will set apply these properties to the current formatting context.
To understand how it works, think of painting-by-numbers. In front of you is a canvas with outlines of shapes and numbers inside the shapes. Each number corresponds to a paint color. You go to each shape, find the paint that corresponds to the number inside it, and fill it in with that color. In an hour or so, you'll have a lovely stylized pastoral scene with a barn and wildflowers. In this analogy, the rule is a paint can with a numbered label. The color is the property and the number is the selector.
The selector can be more complex than just one element name. It can be a comma-separated list of elements. It could be qualified with an attribute, as in this example, which matches a foo element with class="flubber":
foo.flubber { color: green; }
This dot-qualified selector matches an element with a class attribute, which is supported in HTML and SVG.
The CSS processor tries to find the best rule (or rules) for each element. In a stylesheet, several rules may apply. For example:
p.big { font-size: 18pt; } p { font-family: garamond, serif; font-size: 12pt; } * { color: black; font-size: 10pt; }
The first rule matches a p with attribute class="big". The second matches any p regardless of attributes, and the last matches any element at all. Suppose the next element to process is a p with the attribute class="big". All three rules match this element.
How does CSS decide which properties to apply? The solution to this dilemma has two parts. The first is that all rules that match are used. It's as if the property declarations for all the applicable rules were merged into one set. That means all of these properties potentially apply to the element:
font-size: 18pt; font-family: garamond, serif; font-size: 12pt; color: black; font-size: 10pt;
The second part is that redundant property settings are resolved according to an algorithm. As you can see, there are three different font-size property settings. Only one of the settings can be used, so the CSS processor has to weed out the worst two using a property clash resolution system. As a rule of thumb, you can assume that the property from the rule with the most specific selector will win out. The first font-size property originates from the rule with selector p.big, which is more descriptive than p or *, so it's the winner.
In the final analysis, these three properties will apply:
font-size: 18pt; font-family: garamond, serif; color: black;
XML documents have a hierarchy of elements. CSS uses that hierarchy to pass along properties in a process called inheritance. Going back to our DocBook example, a sect1 contains a para. Consider the following stylesheet:
sect1 { margin-left: 25pt; margin-right: 25pt; font-size: 18pt; color: navy; } para { margin-top: 10pt; margin-bottom: 10pt; font-size: 12pt; }
The para's set of properties is a combination of those explicitly declared for it and those it inherits from the elements in its ancestry. Not all properties are inherited. Margins are never inheritable, so in the above example, only font-size and color may be inherited. However, the font-size property is not inherited by para because it is redefined there. So the para's properties include those specifically defined for it, plus the one it inherited, color: navy.
A very powerful feature of CSS is its ability to combine multiple stylesheets by importing one into another. This lets you borrow predefined style definitions so you don't have to continuously reinvent the wheel. Any style settings that you want to redefine or don't need can be overridden in the local stylesheet.
One reason to combine stylesheets is modularity. It may be more manageable to break up a large stylesheet into several smaller files. For example, we could store all the styles pertaining to math equations in math.css and all the styles for regular text in text.css. The command @import links the current stylesheet to another and causes the style settings in the target to be imported:
@import url(http://www.example.org/mystyles/math.css); @import url(http://www.example.org/mystyles/text.css);
Some of the imported style rules may not suit your taste, or they may not fit the presentation. You can override those rules by redefining them in your own stylesheet. Here, we've decided that the rule for h1 elements defined in text.css needs to be changed:
@import url(http://www.example.org/mystyles/text.css); h1: { font-size: 3em; } /* redefinition */