Bert Bos | CSS tutorial – selectors



Selectors - principles

For CSS, a document is always a tree with two kinds of ordered nodes:

Elements have

In HTML, SVG, etc., the classes are carried by one of the attributes.

Examples of trees

Inside and outside the tree

CSS has a handful of pseudo-elements, because typographically interesting components do not always correspond exactly to an element in the document: ::first-line for the first line of a paragraph, :first-letter for the first letter letter or letter combination, ::before for a piece of text that doesn't occur in the document but is implied by the mark-up, etc.

De semantics of hyperlinks will maybe be expressed in CSS some day. Hyperlinks are on the edge of semantics and style and it is difficult in this case to keep them separate. In princip;le, the fact that something is a link is semantics, but whether to present the link as a hyperlink, a transclusion, or something else is style…

XLink and HLink have been attempts to capture the semantics in XML, so that other technologies, such as CSS, could build on it. But they haven't been very successful. Opera has proposed CSS properties ('-o-link').

New in level 3

Sibling elements

E ~ F
an element F that has elder sibling E

  <h1 id=french>French...</h1>
  <h1 id=english>English...</h1>
#french ~ p {
  font-weight: bold;
  color: #077;
  font-size: 1.4em;
  padding-left :1em;

Attribute selectors

an element E that has an attribute called foo

img[alt] {
  border: 10px rgb(147,103,94) solid;
  border-radius: 10px;

Negation selectors

an element E that doesn't match s

img:not([alt]) {
  border: 10px rgb(147,103,94) solid;
  border-radius: 10px;

Attribute contains text

an element E with an attribute foo that contains the text “bar”

a[href*="glossaire"] {
  color: gray;

Attribuut begins with text

an element E with an attribute foo whose value starts with the text “bar”

a[href^="http:"] {

Attribuut ends with text

an element E that has an attribute foo whose value ends with the text “bar”

a[href$=".pdf"]::after {
  vertical-align: -20px;

First child

an element E that is the first child of its parent

th:first-child {
  border-left: none;
  text-align: left }
th:nth-child(1) {            /* same! */
  border-left: none;
  text-align: left }

':First-child' is in level 2. In level 3 we generalized the pseudo-class to select the n'th child, or the first n children, or every n'th child starting with the m'th.

More about ':nth-child()' below.

Last element of a certain type

an element that is the last element of type E in its parent

  border-bottom:2px solid red

The n'th child / every n'th child (1/2)

every second child starting with the 4th (i.e., children 4, 6, 8, 10, etc.)

td:nth-child(2n + 4) {
  background:rgba(29, 53, 91, .3);

Note: no space between the “2” and the “n”!

The n'th child / every n'th child (2/2)

The n in an + b stands for all whole numbers ≥ 0 (i.e., 0, 1, 2,…)

If a or b is 0, you can omit that part:

Negative numbers are allowed (and sometimes useful):

Even and odd

same as nth-child(2n+1)

same as nth-child(2n+2)


Empty elements

an empty element (no text, no children)

th:empty, td:empty{
  background:rgba(253,143,149, .5);

The target of the current URL

the element that is pointed at by the current URL, e.g..:


From the demo:

:target { border:4px gold solid }

If you follow a link to somewhere in the middle of another document, then you can give the element that you jumped to a special style by means of ':target'.

Of course, you can also jump within the same document, e.g., from the table of contents to a section. Some tricks rely on jumping within a document to change the style of the document with every click, such as showing and hiding tabbed cards. (But hopefully one day we'll have ways to do such style changes directly, without the limitations of this trick.)

Check marks

the element is a checkbox that has been checked

input:checked + label {
  font-weight: bold }

Other selectors voor forms: :enabled, :disabled :indeterminate

Selectors exercise

Make a document that allows you to switch which of two texts is visible.

Hint: you can do this with :target and ~, or with :checked and ~ (What is the advantage of :checked over :target in this case?)