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

Try it yourself
Result
Pseudo-classMatches when…
:hoverThe pointer is over the element
:activeIt's being pressed
:focusIt has keyboard focus (from any source, including clicks)
:focus-visibleIt has focus and the browser thinks a focus ring should show (typically keyboard use)
:focus-withinIt 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.

Touch screens: phones can't hover. Never hide important information or actions behind :hover alone.

Link states

Try it yourself
Result

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

Try it yourself
Result
Pseudo-classMatches
:checkedChecked checkboxes, radios and selected options
:disabled / :enabledDisabled or enabled controls
:required / :optionalFields with or without required
:valid / :invalidFields that pass or fail validation (immediately)
:user-valid / :user-invalidSame, but only after the user has interacted
:placeholder-shownInputs currently showing placeholder text

Structural pseudo-classes

Try it yourself
Result
Pseudo-classMatches
:first-child, :last-childFirst / last among siblings
:only-childThe 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
:emptyElements 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

Try it yourself
Result
  • :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.

Try it yourself

Try it yourself
Result