XML.com: XML From the Inside Out
oreilly.comSafari Bookshelf.Conferences.


CSS 3 Selectors

June 18, 2003

Although the promise of Cascading Style Sheets (CSS) has been wondrous, the progress has been wanting. As with all W3C standards, there is the lengthy discussion process conducted by the related working group, then the problem of implementation by web browser vendors, and finally the unpredictable period of time for people to update to new versions of their browser. These steps can take a year or two each. To expedite the process, the CSS working group has started grouping related features into modules and releasing them separately, without waiting for completion of all modules. This allows browser vendors to proceed with implementation of CSS updates with the confidence that standards won't be changed by the time the full release of CSS is approved. Ideally the result will be to reduce the process by a year or more.

One CSS module that is expected shortly to move to Recommended (or finished) status by the CSS working group is the Selectors module. Much of it has already been implemented by some of the browser vendors. The vendors seem very keen to expedite the Selectors module since it can improve HTML and XML document design decidedly and for fairly little effort. As CSS grows, more selectors are adopted, although some can be pruned. This article will review all currently approved selectors. It will address the surviving CSS1 and CSS2 selectors in brief and the new CSS3 selectors in more detail.

Basic Definitions

A cascading style sheet is used to set or change the styles of a markup document like a web page. Style sheets contain rules that web browsers follow when loading a web page, an XML document, or any document written in a compatible markup language. A style sheet rule is composed of two basic components: a selector and a declaration. The selector is an identifier of a markup tag. For example, in HTML, p is the selector for <p> (or paragraph) tags. Declarations are the style settings that are to be applied by the browser when it encounters a match in a document for a selector. There are many different declarations that may be made, but it is only selectors that concern us here. So when providing examples, I will focus on selectors and not comment on declarations.

CSS1 Selector Basics

The basic value of a selector is to point to objects or text for which a designer would like to set the style. For instance, suppose one decided to set to navy blue the main heading of each web page on a site containing over a thousand pages. If all of the pages are linked to the same style sheet and each page's main heading is wrapped in <h1> tags, then the task would be simple and quick. It would be a matter of merely inserting into to the style sheet the simple rule below:

h1{color: navy;}

Occasionally designers need to select elements by class or by unique identifiers. Suppose a web page contains several tables and the designer wants the background color of some tables to be silver. Class selectors can be utilized by assigning a class to tables that are to be colored. One would place the first line below in the style sheet and start off silver tables in the document like the second line:

table.special{background-color: silver;}
 <table class='special'>

To change the style for only one element on a site, an identification (ID) can be used:

table#unique{background-color: pink;}
<table ID='unique'>

In CSS1 a few pseudo-class selectors were provided for anchor (<a>) elements: :link, :visited, :active, :hover, and :focus. These can be used to change the style of links depending on their state or on user interaction. Two pseudo-element selectors were also provided: the ::first-letter and the ::first-line selectors are for styling the first letter and the first line contained between selected tags. Pseudo-elements are distinguished by two colons and they can affect partial content, but the declarations of pseudo-class selectors are applied to all of the content.

A powerful function found in CSS1 is the descendant combinator. It allows the designer to select markup elements contained within another specified element. One simply gives the parent element, then a space followed by the descendant. Don't confuse this syntax with that of grouping selectors (e.g., h1, h2, h3{...}). This rule will make the text within <quote> tags italic and green, but only when inside a paragraph:

p quote{font-style: italic; color: green;}

To style elements contained within elements that are contained within ancestor elements, that is, to style grandchildren elements, one would use an asterisk with spaces around it as a combinator:

p * quote{font-style: italic; color: green;}

From these basic selectors, designers have been able to standardize the styles of markup documents and reduce design and production time significantly for the last few years. This has been especially critical for XML developers since XML doesn't have default styling conventions.

CSS2 Selectors

CSS2 offered a universal selector (*) to allow selection of specified elements of all parents. For instance, this rule will select TD cells of all tables:

*.td{font-size: 85%;}

CSS2 expanded selectors to include discerning the values of element attributes. In HTML an image element (<img/>) may contain attributes like src, alt, align, and border. One can check if an image tag has a specified attribute. To set the padding only for images where the border is given, this rule will suffice:

img[border]{margin: 5px;}

You can also check if a value is contained in a space separated list contained in an attribute (e.g., img[alt~="fish"]{...}). Or one can check the full value for an exact match:

img[src="logo.gif"]{border: 0;}

CSS2 also expanded descendant selector possibilities. The pseudo-element selectors ::before and ::after allow one to add content before and after elements found. If one marked up the text of a play with XML tags around the dialog to identify a character's lines (e.g., <romeo>...</romeo>), one could use CSS to add text before and after each set of lines:

romeo::before{content: "Romeo: \"";}
romeo::after{content: "\"";}

Starting in CSS2, designers can now change the style for the first child of an element. To double the size of the first letter of the first paragraph of each section of a document (provided each section is enclosed in <div class='section'></div> tags), try this:

div.section:first-child::first-letter{font-size: 200%;}

Notice that the parent is div; section is the class, not the child. The child is whatever the browser finds first. It will double the size of the first letter of each child's content.

A child combinator selector was added to be able to style the content of elements contained within other specified elements. For example, suppose one wants to set white as the color of hyperlinks inside of div tags for a certain class because they have a dark background. This can be accomplished by using a period to combine div with the class resources and a greater-than sign as a combinator to combine the pair with a, as shown below:

div.resources > a{color: white;}

Also added in CSS2 was the direct adjacent combinator. For example, imagine you want to indent all paragraphs in a document except for ones immediately following a sub-heading (<h2>). The second rule below shows an h2 selector combined with a p selector using a plus sign as the combinator to indicate that the declaration applies only if p immediately follows h2:

p{text-indent: 0.5in;}
h2 + p{text-indent: 0;}

Finally, consider the language selector. The :lang selector is for selecting a document of a specific language:

html:lang(en){color: black;}
xml:lang(en){color: gray;}

Similarly, the hreflang attribute of the link element can be used with the attribute value selector that checks for a value and the same value followed by a hyphen. The following rule will match French (fr) and Belgian French (fr-be):

link[hreflang|="fr"]{font-style: italic;}

Pages: 1, 2

Next Pagearrow