CSS Selectors :nth-child and the of S clause
CSS is an ever-evolving collection of specifications. That includes selectors. One of the features introduced by the level 4 selectors specification, is the of S clause used with the :nth-child()
and :nth-last-of-child()
pseudoclasses.
Both :nth-child()
and :nth-last-of-child()
—Â along with :nth-of-type()
and :nth-last-of-type()
— are tree-structural, child-indexed pseudoclasses. They accept an argument in the form An+b, where:
- A is a step interval or multiplier for n;
- b is an offset; and
- n is a integer that represents the index of the child element, beginning with 1.
For example, :nth-child( 2n )
selects every even-indexed item, while :nth-child( -1n + 5 )
matches the first five children.1
The of S clause adds an additional filter. Its syntax is An+b of S where S is a selector. It matches the nth element of the elements matched by the selector, S. For example, :nth-child( 2n of .star )
matches every other element with the class .star
, as shown in the image below.
To date (as of March 14, 2023), the of S clause is supported by Safari, Google Chrome, and Microsoft Edge, along with other WebKit-based browsers, such as GNOME Web. It remains an open issue for Firefox/Gecko-based browsers.
of S and Specificity
As a pseudoclass, :nth-child()
has a specificity score of 0,1,0. However, adding the of S clause increases the overall specificity by that of S. In other words, :nth-child( 2n )
has a specificity rank of 0,1,0, but :nth-child(2n of p)
has a specificity of 0,1,1 due to its type selector p
. A selector such as :nth-child( 3n of .items )
has a specificity value of 0,2,0 because it contains one pseudoclass and one class (.items
).2
Keep in mind that when S is a type selector, it's the equivalent of using :nth-of-type()
. A selector such as :nth-child( 2n of p )
matches the same elements as p:nth-of-type( 2n )
and has the same specificity score.
of S and the *-of-type
pseudoclasses
Note that the of S clause does not work with the :nth-of-type()
and :nth-last-of-type()
pseudoclass selectors. Remember that the :nth-of-type()
and :nth-last-of-type()
work with type selectors such as p
, h1
, and div
.
The specification does not define behavior for misusing an of S clause with :nth-of-type()
/:nth-last-of-type()
. Safari and GNOME Web ignore it; :nth-of-type( 3 of .items )
is treated as though it's :nth-of-type( 3 )
.
Testing for of S support
CSS parsing and error handling rules dictate that browsers should ignore rules that they do not understand. You can safely use it in your CSS, although you may want to combine it with @supports
and a fall back.
/* What to do if the browser DOES NOT support of S */
@supports not selector( :nth-child( 2n of .items ) ) {
.items:nth-child( 4n + 1 ) {
background: purple;
}
}
:nth-child( 2n of .items ) {
background: purple;
}
Using of S as an argument for querySelector()
or querySelectorAll()
will also fail in browsers that don't support it. In that case, you can test for support using the CSS.supports()
method and the selector()
function before using it in your code e.g.: CSS.supports( 'selector( :nth-child( 2n of .items ) )' )
.
-
Both the step interval, A and the offset, b can be positive or negative integers. All of these pseudoclasses also accept even and odd keywords as arguments (which are the equivalent of
:nth-child( 2n )
and:nth-child( 2n + 1 )
) When A or b is 0, you don't have to include them. ↩ -
Read the Calculating a selector’s specificity section of the Selectors Level 4 specification if you need a refresher. ↩