5 Selectors

Contents

  1. Pattern matching
  2. Universal selector
  3. Type selectors
  4. Descendant selectors
  5. Child selectors
    1. :first-child pseudo-class
  6. Adjacent selectors
  7. Attribute selectors
    1. Matching attributes and attribute values
      1. Reusing the value of an attribute
    2. The "class" attribute in HTML
  8. ID selectors
  9. Grouping
  10. Pseudo-elements and pseudo-classes
    1. The :first-line pseudo-element
    2. The :first-letter pseudo-element
    3. The :before and :after pseudo-elements
    4. Pseudo-elements with descendant selectors
    5. The Anchor pseudo-classes: :link, :visited, :hover, and :active
    6. Combining pseudo-elements with attribute selectors

5.1 Pattern matching

In CSS, pattern matching rules determine which style rules apply to elements in the document tree. These patterns, called selectors, may range from simple element names to rich contextual patterns. If all conditions in the pattern are true for a certain element, the selector matches the element.

The subject of the pattern is the rightmost part of the pattern (generally an element name). The style information in the declaration block following the pattern applies to the subject of the pattern.

The case-sensitivity of document language element names in selectors depends on the document language. For example, in HTML, element names are case-insensitive, but in XML they are case-sensitive.

The following table summarizes CSS2 selector syntax:

PatternMeaningDescribed in section
*Matches any element.Universal selector
EMatches any E element.Type selectors
A BMatches any B element that is a descendant of an A element.Descendant selectors
A > BMatches any B element that is a child of an element A.Child selectors
A:first-childMatches element A when A is the first child of some other element The :first-child pseudo-class
E + FMatches any F element immediately preceded by an element E.Adjacent selectors
E[foo]Matches any E element with the "foo" attribute set (whatever the value). Attribute selectors
E[foo="warning"]Matches any E element whose "foo" attribute value is exactly equal to "warning". Attribute selectors
E[foo~="warning"]Matches any E element whose "foo" attribute value is a list of space-separated of values, one of which is exactly equal to "warning". Attribute selectors
DIV.warningHTML only. The same as DIV[class~="warning"]. The "class" attribute in HTML
E#myidMatches any E element with the "id" attribute equal to "myid".ID selectors

5.2 Universal selector

The universal selector -- written "*" -- matches the name of any element type. It only matches a single node in the document tree.

In attribute selectors and id selectors, the absence of an explicit element name implies the universal selector. However, we recommend that authors always include the "*" for clarity. For example:

5.3 Type selectors

A type selector matches the name of a document language element type. A type selector matches every instance of the element type in the document tree.

The following type selector matches all H1 elements in the document tree:

  H1 { font-family: Helvetica }

Type selectors may be grouped.

5.4 Descendant selectors

At times, authors may want selectors to match an element that is the descendant of another element in the document tree (e.g., "Match those EM elements that are contained by an H1 element"). Descendant selectors express such a relationship in a pattern. A descendant selector matches when an element B is an arbitrary descendant of some ancestor element A. A descendant selector is made up of two or more selectors separated by whitespace.

For example, consider the following rules:

  H1 { color: red }
  EM { color: red }

Although the intention of these rules is to add emphasis to text by changing its color, the effect will be lost in a case such as:

   <H1>This headline is <EM>very</EM> important</H1>

We address this case by supplementing the previous rules with a rule that sets the text color to blue whenever an EM occurs anywhere within an H1:

  H1 { color: red }
  EM { color: red }
  H1 EM { color: blue }

The third rule will match the EM in the following fragment:

  <H1>This 
     <SPAN class="myclass">headline is <EM>very</EM>
     important</SPAN></H1>

The following selector:

   DIV * P 

matches a P element that is a grandchild or later descendant of a DIV element.

Descendant selectors may be grouped. A descendant selector may also contain attribute selectors.

For example, the following matches any element with an "href" attribute inside a P with class "myclass" inside any DIV:

DIV P.myclass *[href]

5.5 Child selectors

A child selector matches when an element is the child of some element. A child selector is made up of two or more selectors separated by ">".

The following rule sets the style of all P elements that are children of BODY:

  BODY > P { line-height: 1.3 }

Child selectors may be grouped. A child selector may also contain attribute selectors.

Descendant selectors and child selectors may be combined. For instance:

DIV OL > LI P

matches a P element that is a descendant of an LI; the LI element must be the child of an OL element; the OL element must be a descendant of a DIV.

5.5.1 :first-child pseudo-class

The first-child pseudo-class matches an element that is the first child of some other element.

In the following example, the selector matches any P element that is the first child of a DIV element. The rule suppresses indentation for the first paragraph of a DIV:

  DIV > P:first-child { text-indent: 0 }

This selector would match the P inside the DIV of the following fragment:

  <P> The last P before the note.
  <DIV class="note">
     <P> The first P inside the note.
  </DIV>

but would not match the second P in the following fragment:

  <P> The last P before the note.
  <DIV class="note">
     <H2>Note</H2>
     <P> The first P inside the note.
  </DIV>

The following rule sets the font weight to "bold" for any EM element that is some descendant of a P element that is a first child:

  P:first-child EM { font-weight : bold }

Note. Anonymous text boxes are not counted as an element when calculating the first child.

For example, the EM in:

    <P>abc <EM>default</EM> 

is the first child of the P.

5.6 Adjacent selectors

Often, special formatting rules apply when two types of elements appear next to each other in a document. For example, when block-level elements are laid out, the vertical space between them collapses. In this case, the special formatting is handled by the rules for collapsing margins, but in other cases of adjacent selectors, authors may want to specify their own special formatting rules.

Adjacent selectors have the following syntax: E1 + E2, where E2 is the subject of the selector. The selector matches if E1 and E2 share the same parent in the document tree and E1 immediately precedes E2.

Thus, the following rule states that when a P element immediately follows a MATH element, it should not be indented:

  MATH + P { text-indent: 0 } 

The next example reduces the vertical space separating an H1 and an H2 that immediately follows it:

  H1 + H2 { margin-top: -5mm }   

Adjacent selectors may be grouped.

Adjacent selectors may also contain attribute selectors.

Adjacent selectors may be combined with other types of selectors.

Thus, for example, the following rule is similar to the one in the previous example, except that the special formatting only occurs when H1 has class="opener":

  H1.opener + H2 { margin-top: -5mm }   

5.7 Attribute selectors

CSS2 allows authors to specify rules that match according to attributes defined in the document language.

5.7.1 Matching attributes and attribute values

Attribute selectors may match in three ways:

[att]
Match when the element sets the "att" attribute, whatever the value of the attribute.
[att=val]
Match when the element's "att" attribute value is exactly "val".
[att~=val]
Match when the element's "att" attribute value is a space-separated list of "words", one of which is exactly "val". If this selector is used, the words in the value must not contain spaces (since they are separated by spaces).

Attribute values must be quoted or escaped if they are not identifiers.

For example, the following attribute selector matches all H1 elements that specify the "title" attribute, whatever its value:

   H1[title] { color: blue; }

In the following example, the selector matches all SPAN elements whose "class" attribute has exactly the value "example":

   SPAN[class=example] { color: blue; }

Attribute selectors may refer to several attributes, in which case the attribute parts must follow one another, in any order.

Here, the selector matches all SPAN elements whose "hello" attribute has exactly the value "Cleveland" and whose "goodbye" attribute has exactly the value "Columbus":

   SPAN[hello="Cleveland"][goodbye="Columbus"] { color: blue; }

The following rules illustrate the differences between "=" and "~=":

   A[rel~="copyright"] {} /* matches, e.g., <A rel="copyright copyleft ..." */
   TD[colspan="2"] {}     /* matches only <TD colspan="2"> ... */

The following rule hides all elements for which the value of the "lang" attribute is "fr" (i.e., the language is French).

*[LANG=fr] { display : none }

Reusing the value of an attribute  

Authors may use the attr() function to refer to the value of an attribute in a declaration. The function call is replaced by the value of the attribute.

Note. The "attr()" function has not be fully specified as of this draft. One stumbling block concerns the type of the value returned by the function call. For instance, some HTML attributes such as width/height may take several types of values: integers (pixel widths), percentages (percentage widths), and the "*i" values (proportional widths). How are these values to be interpreted (generically) in CSS? The editors welcome suggestions on possible solutions to this problem. For instance, one might have several attr() functions for different, well-defined types: attr-integer(), attr-url(), attr-color(), etc.

5.7.2 The "class" attribute in HTML

For style sheets used with HTML, authors may use the dot (.) notation as an alternative to the "~=" notation. Thus, in HTML, "DIV.value" and "DIV[class~=value]" have the same meaning. The attribute value must immediately follow the ".".

For example, we can assign style information to all elements with class~="pastoral" as follows:

  *.pastoral { color: green }  /* all elements with class=pastoral */

or just to H1 elements with class="pastoral":

  H1.pastoral { color: green }  /* H1 elements with class=pastoral */

Given these rules, the first H1 instance below would not have green text, while the second would:

  <H1>Not green</H1>
  <H1 class="pastoral">Very green</H1>

To match a subset of "class" values, each value must be preceded by a ".", in any order.

For example, the following rule matches any P element whose "class" attribute has been assigned a list of space-separated values that includes "pastoral" and "marine":

 
   P.pastoral.marine { color: green }

This rule matches when class="pastoral blue aqua marine" but does not match for class="pastoral blue".

Similarly, the following aural style sheet rules allow a script to be read aloud in different voices for each role:

   P.role.romeo  { voice-family: romeo, male }
   P.role.juliet { voice-family: juliet, female }

Note. CSS gives so much power to the "class" attribute, that authors could conceivably design their own "document language" based on elements with almost no associated presentation (such as DIV and SPAN in HTML) and assigning style information through the "class" attribute. Authors should avoid this practice since the structural elements of a document language have recognized and accepted meanings and author-defined classes may not.

5.8 ID selectors

The ID attribute of a document language allows authors to assign an identifier to a specific element instance in the document tree. This identifier must be unique in the document tree. CSS ID selectors match an element instance based on its identifier.

Each document language may only contain one ID attribute. In HTML 4.0, the ID attribute is called "id", but in an XML application it may be called something else. The name of the ID attribute is immaterial for CSS.

A CSS "id" selector contains a "#" immediately followed by the "id" value.

The following ID selector matches the H1 element whose "id" attribute has the value "chapter1":

H1#chapter1 { text-align: center }

In the following example, the style rule matches any element that has the "id" value "z98y". The rule will thus match for the P element:

  <HEAD>
  <TITLE>Match P</TITLE>
  <STYLE type="text/css">
     *#z98y { letter-spacing: 0.3em }
  </STYLE>
  </HEAD>
  <BODY>
     <P id=z98y>Wide text</P>
  </BODY>

In the next example, however, the style rule will only match an H1 element that has an "id" value of "z98y". The rule will not match the P element in this example:

  <HEAD>
  <TITLE>Match H1 only</TITLE>
  <STYLE type="text/css">
     H1#z98y { letter-spacing: 0.5em }
  </STYLE>
  </HEAD>
  <BODY>
     <P id=z98y>Wide text</P>
  </BODY>

ID selectors have a higher precedence than attribute selectors. For example, in HTML, the selector #p123 is more specific than [ID=p123] in terms of the cascade.

5.9 Grouping

When several selectors share the same declarations, they may be grouped into a comma-separated list.

In this example, we condense three rules with identical declarations into one. Thus,

  H1 { font-family: Helvetica }
  H2 { font-family: Helvetica }
  H3 { font-family: Helvetica }

is equivalent to:

  H1, H2, H3 { font-family: Helvetica }

CSS offers other "shorthand" mechanisms as well, including multiple declarations and shorthand properties.

5.10 Pseudo-elements and pseudo-classes

In CSS2, style is normally attached to an element based on its position in the document tree. This simple model is sufficient for many cases, but some common publishing scenarios (such as changing the font size of the first letter of a paragraph) may be independent of the document tree. For instance, in [HTML40], no element refers to the first line of a paragraph, and therefore no simple CSS selector may refer to it.

CSS introduces the concepts of pseudo-elements and pseudo-classes to permit formatting based on information that lies outside the document tree.

Pseudo-classes are allowed anywhere in selectors while pseudo-elements may only appear as the last segment of a selector.

Although pseudo-elements and pseudo-classes do not exist in the document tree, their behavior is defined as if they did. Each pseudo-element and pseudo-class may be modeled by a fictional tag sequence, a fragment of document source that includes imaginary elements from the document language. The fictional tag sequence is only a model used to describe the rendering effects of pseudo-elements and pseudo-classes and does not indicate how these should be implemented.

Pseudo-elements and pseudo-class names are case-insensitive.

Several pseudo-element rules may have an impact on the same content. These are called overlapping pseudo-elements. An example is provided below.

Conforming HTML user agents may skip all rules with :first-line or :first-letter in the selector, or, alternatively, may only support a subset of the properties on these pseudo-elements.

Note. In CSS2, only one pseudo-element can be specified per selector. This may change in future versions of CSS.

5.10.1 The :first-line pseudo-element

The :first-line pseudo-element applies special styles to the first formatted line of a paragraph. For instance:

  P:first-line { font-variant: small-caps }

The above rule means "change the font variant of the first line of every paragraph to small-caps". However, the selector "P:first-line" does not match any real HTML element. It does match a pseudo-element that conforming user agents will insert at the beginning of every paragraph.

Note that the length of the first line depends on a number of factors, including the width of the page, the font size, etc. Suppose for this example that the paragraph is broken into the lines indicated in the example. Thus, an ordinary HTML paragraph such as:

  <P>This is a somewhat long HTML paragraph that will
  be broken into several lines. The first line will be
  identified by a fictional tag sequence. The other lines will 
  be treated as ordinary lines in the paragraph.</P>

might be "rewritten" by user agents to include the fictional tag sequence for :first-line.

  <P>
  <P:first-line>This is a somewhat long HTML paragraph that will</P:first-line>
  be broken into several lines. The first line will be
  identified by a fictional tag sequence. The other lines will 
  be treated as ordinary lines in the paragraph.</P>

If a pseudo-element breaks up a real element, the necessary extra tags must be regenerated in the fictional tag sequence. Thus, if we mark up the previous paragraph with a SPAN element:

  <P><SPAN class="test">This is a somewhat long HTML paragraph that will
  be broken into several lines.</SPAN> The first line will be
  identified by a fictional tag sequence. The other lines will 
  be treated as ordinary lines in the paragraph.</P>

The user agent should generate the appropriate start and end tags for SPAN when inserting the fictional tag sequence for :first-line.

  <P><P:first-line><SPAN class="test">This is a somewhat long HTML paragraph that will</SPAN></P:first-line>
  <SPAN>be broken into several lines.</SPAN> The first line will be
  identified by a fictional tag sequence. The other lines will 
  be treated as ordinary lines in the paragraph.</P>

The :first-line pseudo-element can only be attached to a block-level element.

The :first-line pseudo-element is similar to an inline element, but with certain restrictions. Only the following properties apply to a :first-line element: font properties, color properties, background properties, 'word-spacing', 'letter-spacing', 'text-decoration', 'vertical-align', 'text-transform', 'line-height', and 'clear'.

5.10.2 The :first-letter pseudo-element

[Define better alignment of drop caps? BB]

The :first-letter pseudo-element may be used for "initial caps" and "drop caps", which are common typographical effects. This type of initial letter is similar to an inline element if its 'float' property is 'none', otherwise it is similar to a floating element.

These are the properties that apply to :first-letter pseudo-elements: font properties, color properties, background properties, 'text-decoration', 'vertical-align' (only if 'float' is 'none'), 'text-transform', 'line-height', margin properties, padding properties, border properties, 'float', and 'clear'.

The following CSS2 will make a dropcap initial letter span two lines:

<HTML>
 <HEAD>
  <TITLE>Dropcap initial letter</TITLE>
  <STYLE type="text/css">
   P              { font-size: 12pt; line-height: 12pt }
   P:first-letter { font-size: 200%; font-style: italic; font-weight: bold; float: left }
   SPAN           { text-transform: uppercase }
  </STYLE>
 </HEAD>
 <BODY>
  <P><SPAN>The first</SPAN> few words of an article in The Economist.</P>
 </BODY>
</HTML>

This example might be formatted as follows:

Image illustrating the combined effect of the :first-letter and :first-line pseudo-elements

The fictional tag sequence is:

  <P>
  <SPAN>
  <P:first-letter>
  T
  </P:first-letter>he first
  </SPAN> 
  few words of an article in the Economist.
  </P>

Note that the :first-letter pseudo-element tags abut the content (i.e., the initial character), while the :first-line pseudo-element start tag is inserted right after the start tag of the element to which it is attached.

The UA defines what characters are inside the :first-letter element. Quotes that precede the first letter should be included, as in:

Quotes that precede the
first letter should be included.

When the paragraph starts with other punctuation (e.g., parenthesis and ellipsis points) or other characters that are normally not considered letters (e.g., digits and mathematical symbols), :first-letter pseudo-elements are generally skipped

The :first-letter pseudo-element can only be attached to a block-level element.

Note. Some languages may have specific rules about how to treat certain letter combinations. In Dutch, for example, if the letter combination "ij" appears at the beginning of a word, they should both be considered within the :first-letter pseudo-element.

The following example illustrates how overlapping pseudo-elements may interact. The first letter of each P element will be green with a font size of '24pt'. The rest of the first formatted line will be 'blue' while the rest of the paragraph will be 'red'.

  P { color: red; font-size: 12pt }
  P:first-letter { color: green; font-size: 200% }
  P:first-line { color: blue }

  <P>Some text that ends up on two lines</P>

Assuming that a line break will occur before the word "ends", the fictional tag sequence for this fragment might be:

  <P>
  <P:first-line>
  <P:first-letter> 
  S 
  </P:first-letter>ome text that 
  </P:first-line> 
  ends up on two lines 
  </P>

Note that the :first-letter element is inside the :first-line element. Properties set on :first-line are inherited by :first-letter, but are overridden if the same property is set on :first-letter.

When the :first-letter and :first-line pseudo-elements are combined with :before and :after, they apply to the first letter or line of the element including the inserted text.

5.10.3 The :before and :after pseudo-elements

The ':before' and ':after' pseudo-elements can be used to insert fixed text before or after an element. They are explained in the section on generated text.

5.10.4 Pseudo-elements with descendant selectors

In a descendant selector, pseudo-elements are only allowed at the end of the selector.

The following example illustrates this with the :first-letter pseudo-element.

  BODY P:first-letter { color: purple }

Pseudo-classes, however, may be used anywhere in a descendant selector.

The following example sets the border color to blue of all images that descend from A elements that have not yet been visited:

  A:link IMG { border: solid blue }

5.10.5 The Anchor pseudo-classes: :link, :visited, :hover, and :active

User agents commonly display unvisited links differently from previously visited ones. CSS2 allows authors to specify the rendering of a link in one of several states:

The four states are mutually exclusive. If a link qualifies for several states, the order of preference is: active, hover, visited, link.

User agents are not required to reflow a currently displayed document due to anchor pseudo-class transitions. For instance, a style sheet may legally specify that the 'font-size' of an :active link should be larger that a :visited link, but the UA is not required to dynamically reflow the document when the reader selects the :visited link.

  A:link { color: red }       /* unvisited links */
  A:visited { color: blue }   /* visited links   */
  A:hover { color: yellow }   /* user hovers     */
  A:active { color: lime }    /* active links    */

In HTML, the following two CSS2 declarations are equivalent and select the same elements:

  A:link { color: red }
  :link { color: red }

5.10.6 Combining pseudo-elements with attribute selectors

Pseudo-classes can be combined with attribute selectors. In this case, the class name must precede the pseudo-class name in the selector.

If the following link:

  <P>
  <A class="external" href="http://out.side/">external link</A>

has been visited, this rule:

  A.external:visited { color: blue }

will cause it to be blue.

Pseudo-elements can also be combined with attribute selectors.

Thus, the following rule:

  P.initial:first-letter { color: red }

would make the first letter of all P elements with class="initial" such as the following, the color 'red', as in:

  <P class="initial">First paragraph</P>

Pseudo-elements must be specified at the end of a selector.