Styling every other row in a table, or highlighting only the third item in a list, sounds trivial, but it requires a tool capable of counting. That is exactly what the :nth-child() pseudo-class does, through a compact mathematical formula.
It has a reputation for being intimidating because of its an+b syntax, even though a handful of examples is enough to make it perfectly readable in everyday use.
Definition
The :nth-child() pseudo-class targets an element based on its position among its parent's children, counting every type of tag together. It accepts a simple keyword like odd or even, or a formula of the form an+b.
Understanding the an+b formula
In the formula, n stands for a counter that starts at 0 and increases indefinitely (0, 1, 2, 3...), a is the multiplier, and b is an offset added to the result. Substituting each integer value for n produces the list of targeted positions.
/* every other row, the even ones: 2, 4, 6... */
tr:nth-child(2n) {
background-color: #f5f5f5;
}
/* every other row, the odd ones: 1, 3, 5... */
tr:nth-child(2n + 1) {
background-color: white;
}
/* every third item: 3, 6, 9... */
li:nth-child(3n) {
border-bottom: 2px solid #ddd;
}
/* only the third item */
li:nth-child(3) {
font-weight: bold;
}With 2n, the formula produces 0, 2, 4, 6, which matches the even positions since positions start at 1 in HTML. With 2n + 1, it produces 1, 3, 5, 7, the odd positions. A number on its own, with no n, targets a single fixed position, like :nth-child(3) for only the third child.
The difference with :nth-of-type
:nth-child() counts every child of the parent, regardless of tag type, while :nth-of-type() only counts elements of the same type as the one being targeted. On a parent that mixes different tags, such as a heading followed by several paragraphs, these two pseudo-classes can give very different results for the exact same formula.
| HTML | p:nth-child(2) | p:nth-of-type(2) |
|---|---|---|
h2, p, p, p | No match (position 2 is a p, but the h2 counts too) | The second p, position 3 |
:nth-child() seems to match nothing even though the formula looks correct, check whether the parent mixes other tag types. In that case, :nth-of-type() is often the choice that actually matches the intent.Striping a table cleanly
The most common example of :nth-child() remains striping a table, where every other row receives a slightly different background to make a long table easier to read. This technique belongs to the same family as other Pseudo-class selectors that describe a position, and pairs well with a custom list-style when the formula applies to a list rather than a table.
tbody tr:nth-child(odd) {
background-color: #fafafa;
}
tbody tr:nth-child(even) {
background-color: #ffffff;
}This formula works no matter how many rows the table has, with no need to ever recalculate positions by hand when a row gets added or removed, which makes it a far more robust solution than a class placed manually on every other row.
Frequently asked questions
The formula :nth-child(n + 2) targets everything from the second position onward, which excludes the first element. It can then be combined with :not(:last-child) to also exclude the last one.
odd and even be used instead of a formula?Yes, :nth-child(odd) is exactly equivalent to :nth-child(2n + 1), and :nth-child(even) is equivalent to :nth-child(2n), which makes the code more readable for these two very common cases.
Not with :nth-child(), which always counts from the start. To count from the end, a separate pseudo-class exists, :nth-last-child(), which uses the same formula syntax.