Pseudo-classes
Pseudo-classes select elements in a particular state or position: being hovered, focused or checked; being the first child; being an invalid form field. They're written with a single colon, like :hover, and make interfaces feel alive without any JavaScript.
User-action states
| Pseudo-class | Matches when… |
|---|---|
:hover | The pointer is over the element |
:active | It's being pressed |
:focus | It has keyboard focus (from any source, including clicks) |
:focus-visible | It has focus and the browser thinks a focus ring should show (typically keyboard use) |
:focus-within | It or anything inside it has focus |
Use :focus-visible for focus rings: keyboard users see a clear outline, while mouse clicks don't leave one behind. Never remove focus styles without providing a replacement.
:hover alone.Link states
For links, the order :link, :visited, :hover, :active matters, because later rules override earlier ones of equal specificity (mnemonic: "LoVe HAte"). For privacy, browsers only let :visited change colours.
Form states
| Pseudo-class | Matches |
|---|---|
:checked | Checked checkboxes, radios and selected options |
:disabled / :enabled | Disabled or enabled controls |
:required / :optional | Fields with or without required |
:valid / :invalid | Fields that pass or fail validation (immediately) |
:user-valid / :user-invalid | Same, but only after the user has interacted |
:placeholder-shown | Inputs currently showing placeholder text |
Structural pseudo-classes
| Pseudo-class | Matches |
|---|---|
:first-child, :last-child | First / last among siblings |
:only-child | The sole child of its parent |
:nth-child(n) | By position: 3, odd, even, 3n, 2n+1, -n+3 (first three) |
:nth-last-child(n) | Counting from the end |
:first-of-type, :nth-of-type(n) | Same, counting only elements of the same tag |
:empty | Elements with no children or text |
In an + b formulas, n counts 0, 1, 2…: 3n+1 matches items 1, 4, 7. :nth-child(2 of .selected) even counts only elements matching a selector.
Other useful pseudo-classes
:target— the element whose id matches the URL fragment.:not(selector)— everything except matches.:root— the document's root element (<html>), where global variables usually live.:has(),:is()and:where()— powerful modern selectors covered in lesson 43.