Structural pseudo-classes select by position among siblings. In An+B, n runs 0, 1, 2..., so 2n+1 gives 1, 3, 5 and -n+3 the first three. All weigh 0-1-0; :nth-child(An+B of S) also adds the weight of S.
| Selector | Matches |
|---|---|
| :first-child / :last-child / :only-child | First / last / sole child of its parent |
| tr:nth-child(odd) / :nth-last-child(2) | Rows 1, 3, 5... / second from the end |
| li:nth-child(2 of .done) | The second child that has class done |
| p:first-of-type / p:nth-of-type(3) | First / third <p>, ignoring other tags |
| p:empty | A <p> with no children, not even whitespace |
p:first-child needs a <p> that is literally first; p:first-of-type skips a leading <h3>. The of S form (Baseline widely available since November 2025) counts only siblings matching S, so stripes survive hidden rows.
<!doctype html>
<style>
body { font: 15px system-ui; } p { margin: 0; }
ul { display: flex; gap: 4px; list-style: none; padding: 0; margin: 0 0 8px; }
li { padding: 2px 10px; } li:last-child { box-shadow: inset 0 -3px #1565c0; }
li:nth-child(odd of :not([hidden])) { background: #e3f2fd; }
div p:first-of-type { font-weight: 700; } div :empty { height: 6px; background: #ef6c00; }
</style>
<ul><li>One</li><li hidden>Hidden</li><li>Two</li><li>Three</li><li>Four</li></ul>
<div><b>Notes:</b><p>First p, bold via :first-of-type</p><p></p></div>