Structural Pseudo-ClassesBy Alexis Goldstein , Estelle Weyl , Louis Lazaris
The following is an extract from our book, HTML5 & CSS3 for the Real World, 2nd Edition, written by Alexis Goldstein, Louis Lazaris, and Estelle Weyl. Copies are sold in stores worldwide, or you can buy it in ebook form here.
So far, we’ve seen how we can target elements based on their attributes and states. CSS3 also enables us to target elements based simply on their location in the markup. These selectors are grouped under the heading structural pseudo-classes.
These might seem complicated right now, but they’ll make more sense as we look at ways to apply them later on. These selectors are supported in IE9 and newer, as well as current and older versions of all the other browsers but not in IE8 and below:
The root element, which is the
html element in our HTML files.
E that is the
nth child of its parent. The
n parameter is explained in the note below.
F that is the
nth child of its parent
E, counting backwards from the last one.
li:nth-last-child(1) would match the last item in any listthis is the same as
(see the note below).
The element that is the
nth element of its type in a given parent element.The difference between
:nth-of-type is explained in the note below.
nth-of-type(n), except counting backwards from the last element in a parent.
Note: Parameters of Structural Selectors
There are four pseudo-classes that take the equation
an+b as a parameter in parentheses, or the keywords
even. The structural pseudo-classes include
:nth-child(an + b),
:nth-last-child(an + b),
:nth-of-type(an + b), and
:nth-last-of-type(an + b). In the equation
a is the multiplier as an integer,
b is the offset as an integer, and
n is always the variable
In the simplest case, you can pass an integer. For example,
E:nth-of-type(3) will target the third
E element child of a single parent element. You can pass one of the two keywords
even, targeting every other element. You can also, more powerfully, pass a
number expression such as
3n means every third element, defining the frequency, and
+1 is the offset. The default offset is zero, so where
:nth-of-type(3n) would match the 3rd, 6th, and 9th elements in a series,
:nth-of-type(3n+1 would match the 1st, 4th, 7th, and so on.
Negative offsets are also allowed. CSS is based on linguistic languages, not programming languages, so the count starts at
0. There can be no space between the multiplier
a and the variable
n, and the offset must come last.
With these numeric pseudo-classes, you can pinpoint which elements you want to target without adding classes to the markup. The most common example is a table where every other row is a slightly darker color to make it easier to read. We used to have to add odd or even classes to every
tr to accomplish this. Now, we can simply declare
tr:nth-of-type(odd) to target every odd line without touching the markup. You can even take it a step further with three-colored striped tables: target
tr:nth-of-type(3n+2) and apply a different color to each.
E is the first child of its parent. This is the same as
E is the last child of its parent, same as
The same as
The same as
E is the only child of its parent.
E is the only element of type
E that is a direct child of its parent element.
Note: Child versus Type
In employing the structural selectors of
nth-child, its important to understand what child and type mean in this case. Child looks at all the child elements that match the count and check if the precursor is a match. Type looks at all the elements that match the precursor first, then matches based on the count.
In the case of
p:nth-child(3n), the browser looks at every third child of a parent. If that child is a
p, there is a match; if not, no match. In the case of
p:nth-of-type(3n), the browser looks at all the
p children of the parent, and matches every third
Structural pseudo-classes are based on the parent, and restart counting for each new parent. They only look at elements that are the direct children of the parent. Text nodes are not part of the equation.
An element that has no children; this includes text nodes, so
<p> </p> will not be matched by
<p><!-- comment --></p> will be. This selector also matches empty or void elements, such as
<input> . In CSS Selectors Level 4, well get
p:blank that will match
An element in the language denoted by the two-letter abbreviation, such as
E:[lang|=en], where the
lang attribute must be present as an attribute of element
E:lang(en) will match
E if the language was declared on the element itself or any ancestor.
This is a particularly useful one: it will select elements that dont match the selector in the parentheses.
Selectors with the
:not pseudo-class match everything to the left of the colon, and then exclude from that matched group the elements that also match whats to the right of the colon. The left-hand side matching goes first. For example,
p:not(.copyright) will match all the paragraphs in a document first, and then exclude all the paragraphs from the set that also have the class of
copyright. You can string several
:not pseudo-classes together.
input:not([type=checkbox]):not([type=radio]) will match all
input elements on a page except those that are of type