Go back to home page of Unsolicited Advice from Tiffany B. Brown

CSS Selectors :nth-child and the of S clause

An illustration of how the nth-child pseudoclass works with the of S clause. There are ten elements. Every odd element is a purple hexagon. Every even element is a star. Of the star elements, the first, third, and fifth stars are blue. The second and fourth stars are orange.
An illustration of how the nth-child pseudoclass works with the of S clause. There are ten elements. Every odd element is a purple hexagon. Every even element is a star. Of the star elements, the first, third, and fifth stars are blue. The second and fourth stars are orange.

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.

10 alternating hexagon and star shapes. The stars are magenta. The hexagons are black. The second and fourth stars (which are the fourth and eight shapes) also have a green dashed outline.
How the of S clause changes which child elements are matched. View a demo (requires a WebKit-based browser such as Safari or GNOME Web).

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 ) )' ).


  1. 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. 

  2. Read the Calculating a selector’s specificity section of the Selectors Level 4 specification if you need a refresher.