CSS Pseudo-classes & Pseudo-elements Reference

1. What Are Pseudo-classes?

A pseudo-class is a keyword added to a selector that specifies a special state of the selected element.

They let you style elements based on user interaction, form validation state, document structure, or other conditions without adding extra classes or IDs in HTML.

2. User Action Pseudo-classes

These pseudo-classes apply styles based on user interactions, improving the user experience.

Pseudo-class Description Example
:active Matches an element while it is being activated (e.g., between mousedown and mouseup). button:active { background: red; }
:hover Matches when the user hovers over an element. a:hover { color: blue; }
:focus Matches when an element has focus (e.g., clicked into or navigated via keyboard). input:focus { border: 2px solid blue; }
:focus-within Matches an element if it or any of its descendants have focus. form:focus-within { background: #f0f0f0; }

3. Form & Input State Pseudo-classes

Used to style form elements based on their state or validation.

Pseudo-class Description Example
:enabled Matches inputs that are currently enabled. input:enabled { background: white; }
:disabled Matches inputs that are disabled. button:disabled { opacity: 0.5; }
:checked Matches checked checkboxes, radio buttons, or selected <option>. input:checked + label { color: green; }
:valid Matches inputs whose value satisfies validation constraints. input:valid { border: 2px solid green; }
:invalid Matches inputs whose value fails validation. input:invalid { border: 2px solid red; }
:in-range Matches inputs whose value is within a specified min/max. input:in-range { background: lightgreen; }
:out-of-range Matches inputs whose value is outside min/max. input:out-of-range { background: pink; }
:required Matches inputs with the required attribute. input:required { border-left: 4px solid orange; }
:optional Matches inputs without required. input:optional { border-left: 4px solid gray; }
:-webkit-autofill Styles fields filled automatically by the browser. (Vendor-specific) input:-webkit-autofill { background: yellow; }

4. Link & Location Pseudo-classes

These target links or elements related to navigation.

Pseudo-class Description Example
:any-link Matches :link and :visited together. a:any-link { color: blue; }
:link Matches unvisited links. a:link { color: blue; }
:visited Matches visited links. a:visited { color: purple; }
:local-link (Low support) Matches links to the same document. a:local-link { font-weight: bold; }
:target Matches an element targeted by a URL fragment (#id). section:target { background: yellow; }
:target-within Matches an element if it or its descendants are the URL fragment target. div:target-within { outline: 2px solid red; }

5. Tree-Structural Pseudo-classes

Used to style elements based on their position in the DOM tree.

Pseudo-class Description Example
:root Matches the root element (<html> in HTML). :root { --main-color: #333; }
:empty Matches elements with no children (including text nodes). p:empty { display: none; }
:first-child Matches the first child of a parent. li:first-child { font-weight: bold; }
:last-child Matches the last child of a parent. li:last-child { color: red; }
:only-child Matches an element that is the only child of its parent. p:only-child { font-style: italic; }
:first-of-type Matches the first element of its type in a parent. p:first-of-type { text-transform: uppercase; }
:last-of-type Matches the last element of its type in a parent. p:last-of-type { color: orange; }
:only-of-type Matches an element that is the only one of its type in a parent. h1:only-of-type { text-align: center; }
:nth-child(n) Matches the nth child regardless of type. li:nth-child(2) { color: blue; }
:nth-last-child(n) Matches the nth child counting from the end. li:nth-last-child(1) { color: red; }
:nth-of-type(n) Matches the nth element of its type. p:nth-of-type(2) { background: yellow; }

6. Functional Pseudo-classes

Allow more complex selectors by accepting arguments.

Pseudo-class Description Example
:is() Matches if element satisfies any selector in a list. p:is(.intro, .highlight) { color: red; }
:where() Same as :is() but specificity is always 0. :where(h1, h2, h3) { margin: 0; }
:has() Matches an element if it contains elements matching a selector. article:has(h2) { border: 1px solid pink; }
:not() Matches elements that do not match the selector. p:not(.special) { color: gray; }

7. Pseudo-elements

Pseudo-elements let you style specific parts of an element's content.

They use :: (double colon) in modern CSS, but single colon : is still supported for older browsers.

Pseudo-element Description Example
::before Inserts generated content before the element's content. p::before { content: "★ "; }
::after Inserts generated content after the element's content. p::after { content: " ★"; }
::first-letter Styles the first letter of the element. p::first-letter { font-size: 2em; }
::marker Styles list item markers (bullets, numbers). li::marker { color: red; }

Quick Notes

  • Pseudo-class = element state
    Example: a:hover → styles link when hovered.
  • Pseudo-element = part of element
    Example: p::first-letter → styles only the first letter.
  • Not all pseudo-classes have full browser support (e.g., :local-link is experimental).
  • :has() is powerful but can be performance-heavy on large DOMs.