The :nth-child() pseudo-class matches elements by their 1-based index among all sibling children of the same parent — any tag type counts in the position.
Use it for zebra stripes, “every third item,” or “the first three.” Example: li:nth-child(odd) styles items 1, 3, 5, ….
Baseline — widely available.
Core odd / even / An+B patterns are long-supported. The newer of <selector> form has narrower historical support — treat it as progressive when you need filtered counting.
Syntax
CSS Syntax
syntax.css
:nth-child(<An+B> | even | odd)
Optional filter: :nth-child(even of .noted). Examples: :nth-child(3), :nth-child(2n), :nth-child(-n+3).
Patterns
Pattern Values
Pass one pattern that describes which sibling indices to match:
Formula: for n = 0, 1, 2, … compute -n+3 → 3, 2, 1 (then 0, −1… ignored).
Positive indices 1–3 match. Items 4 and 5 do not.
n+4 would mean “from the 4th onward.”
Handy for “top N” badges without markup changes.
Edge Cases & Pitfalls
Most confusion comes from counting all siblings, not only matching tags.
counting
Every sibling counts
A nested em or text wrapper still takes an index. Prefer :nth-of-type() when you only want same-tag positions.
index
Starts at 1, n starts at 0
Elements are 1-based. In An+B, n runs 0, 1, 2, … so 5n first hits 5 (not 0).
of
of changes what you count
:nth-child(2 of .noted) is the 2nd .noted sibling — not “the 2nd child if it has .noted.” Test support before relying on it.
hidden
Hidden rows still occupy a slot
Zebra stripes can look broken when a row is hidden. Filtered counting (even of :not([hidden])) can fix that where supported.
Compatibility
Browser Support
:nth-child() is a browser CSS pseudo-class. Node.js, Deno, and Bun do not apply it.
✓ Baseline · Widely available
:nth-child()
odd, even, and An+B have been available across browsers for years (CSS3 Selectors). The of <selector> syntax is newer — check support if you need filtered counting. Internet Explorer 9+ supports the classic form.
98%Widely available
Google ChromeSupported
Full An+B · of modern
Mozilla FirefoxSupported
Full An+B · of modern
Apple SafariSupported
Full An+B · of modern
Microsoft EdgeSupported
Full An+B · of modern
OperaSupported
Full An+B
Samsung InternetSupported
Full An+B
Internet Explorer9+
Classic An+B · no of
:nth-child()Baseline · Widely available
Bottom line: Safe for zebra stripes and An+B patterns everywhere modern. Use of selectively. This is not a JavaScript runtime API.
Remember
Key Takeaways
Role: select by sibling position (1-based) among all children.
Shortcuts:odd = 2n+1, even = 2n.
Start simple:li:nth-child(odd) { … }.
Same-tag counting? Use :nth-of-type() instead.
One line::nth-child() paints by position in the sibling list — count carefully, style lightly.
Frequently Asked Questions
It matches elements by their 1-based position among all sibling children of the same parent. You pass odd, even, a number, or an An+B formula.
At 1. :nth-child(1) is the first child. The variable n in An+B starts at 0, but element indices still begin at 1.
:nth-child() counts every sibling regardless of tag. :nth-of-type() counts only siblings of the same element type.
Yes. odd and 2n+1 both match positions 1, 3, 5, …. even matches the same set as 2n.
You can write :nth-child(even of .noted) to count only among elements that match a filter. Support for of is newer than basic An+B; test when you need it.
No. It is a browser CSS selector. Node.js, Deno, and Bun do not apply it.