---
title: "CSS Pseudo-Classes and Pseudo-Elements Cheatsheet"
slug: "css-pseudo-classes"
category: "cheatsheets"
tags: ["cheatsheets", "css", "selectors", "pseudo-classes", "pseudo-elements", "frontend"]
status: "stable"
last_updated: 2026-09-27
summary: "Lookup tables for CSS state and structural pseudo-classes (:hover, :focus-visible, :nth-child, :nth-of-type) and pseudo-elements (::before, ::marker, ::backdrop) with specificity."
related: ["[[cheatsheets/css-selectors]]", "[[frontend/css]]", "[[frontend/css-has-selector]]", "[[frontend/keyboard-accessibility]]", "[[frontend/forms]]"]
---

## Overview

Pseudo-classes select elements by state or position; pseudo-elements select parts of an element that are not separate nodes. Every pseudo-class here scores (0,0,1,0), the same as a class; every pseudo-element scores (0,0,0,1), the same as a type selector. For basic, attribute, combinator, and logical selectors (`:is`, `:where`, `:not`, `:has`), see [[cheatsheets/css-selectors]].

## Pseudo-classes (state)

State-based selectors react to user input, structure, or form data.

| Pseudo-class          | Matches                                  | Specificity |
| --------------------- | ---------------------------------------- | ----------- |
| `:hover`              | Mouse is over the element.               | (0,0,1,0)   |
| `:focus`              | Element has keyboard focus.              | (0,0,1,0)   |
| `:focus-visible`      | Focus from keyboard, not click.          | (0,0,1,0)   |
| `:active`             | Element is being activated.              | (0,0,1,0)   |
| `:checked`            | Checkbox or radio is checked.            | (0,0,1,0)   |
| `:disabled`           | Form control is disabled.                | (0,0,1,0)   |
| `:required`           | Form control has `required`.             | (0,0,1,0)   |
| `:valid` / `:invalid` | Form value passes / fails validation.    | (0,0,1,0)   |
| `:empty`              | Element has no children, including text. | (0,0,1,0)   |
| `:target`             | Element matches the URL fragment.        | (0,0,1,0)   |
| `:root`               | The document root (usually `<html>`).    | (0,0,1,0)   |
| `:link` / `:visited`  | Anchor link state.                       | (0,0,1,0)   |

Use `:focus-visible` for focus rings; it skips the ring on mouse clicks while keeping it for keyboard users.

## Pseudo-classes (structural)

Position within a parent. The `n` is a 1-based index.

| Pseudo-class         | Matches                                      |
| -------------------- | -------------------------------------------- |
| `:first-child`       | First child of its parent.                   |
| `:last-child`        | Last child of its parent.                    |
| `:only-child`        | Sole child of its parent.                    |
| `:first-of-type`     | First element of its type among siblings.    |
| `:last-of-type`      | Last element of its type among siblings.     |
| `:nth-child(2)`      | Second child of its parent.                  |
| `:nth-child(odd)`    | 1st, 3rd, 5th, ...                           |
| `:nth-child(2n+1)`   | Same as odd.                                 |
| `:nth-child(3n)`     | Every third child.                           |
| `:nth-last-child(1)` | Counted from the end; same as `:last-child`. |
| `:nth-of-type(2)`    | Second of its type.                          |

`:nth-child` counts siblings of any type; `:nth-of-type` counts siblings of the same type. They are not interchangeable: `p:nth-child(2)` matches a `p` only if it is also the second child overall.

## Pseudo-elements

Pseudo-elements address parts of an element that are not separate elements.

| Pseudo-element   | Targets                                         | Specificity |
| ---------------- | ----------------------------------------------- | ----------- |
| `::before`       | Generated content before the element.           | (0,0,0,1)   |
| `::after`        | Generated content after the element.            | (0,0,0,1)   |
| `::first-line`   | First rendered line of a block.                 | (0,0,0,1)   |
| `::first-letter` | First letter of the first line.                 | (0,0,0,1)   |
| `::marker`       | List bullet or number.                          | (0,0,0,1)   |
| `::placeholder`  | Form control placeholder.                       | (0,0,0,1)   |
| `::selection`    | Currently selected text.                        | (0,0,0,1)   |
| `::backdrop`     | Backdrop of a `<dialog>` or fullscreen element. | (0,0,0,1)   |

Pseudo-elements use double colons (`::`); the single-colon form (`:before`) is the CSS2 spelling and still works for the originals.

## Related

- [[cheatsheets/css-selectors]]: basic, attribute, combinator, and logical selectors
- [[frontend/css]]
- [[frontend/css-has-selector]]
- [[frontend/keyboard-accessibility]]
- [[frontend/forms]]
- [[cheatsheets/index|Cheatsheets]]
