CSS Pseudo-Classes Reference

Every CSS pseudo-class with syntax, applies-to and browser support status.

A searchable CSS pseudo-class reference covering structural, state, linguistic and functional pseudo-classes like :nth-child(), :focus-visible, :has() and :is(), with syntax, what each applies to and support.

What is the difference between a pseudo-class and a pseudo-element?

A pseudo-class uses a single colon (like :hover) and selects existing elements based on their state or position in the tree. A pseudo-element uses double colons (like ::before) and targets a sub-part of an element or generated content.

This is a searchable reference for CSS pseudo-classes — the single-colon selectors that match elements based on their state, position in the document tree, or relationship to other elements. It covers the structural, input-state, linguistic, location and functional pseudo-classes you reach for when styling links, form controls, list items and interactive widgets.

How it works

A pseudo-class is written as a colon followed by a keyword, optionally with arguments in parentheses. Unlike a class attribute, it is not present in your markup — the browser evaluates it dynamically. State pseudo-classes such as :hover, :focus and :checked react to user interaction or form state. Tree-structural ones such as :first-child and :nth-child() match by position among siblings. The :nth-child() family uses an An+B micro-syntax: A is the cycle size, n counts from zero, and B is the offset, so :nth-child(3n+1) matches the 1st, 4th, 7th child and so on. Functional pseudo-classes — :is(), :where(), :not() and :has() — take selector lists and combine logic; :has() is the long-awaited relational (“parent”) selector.

Specificity and tips

Most pseudo-classes add the weight of a class (the middle digit of specificity). The exceptions matter: :where() always adds zero, and :is() / :not() / :has() inherit the specificity of their most specific argument. Use :focus-visible instead of :focus so you only show focus rings for keyboard users, and reach for :focus-within to style a container when any child is focused. Note that :empty treats whitespace as content, so a node containing only spaces will not match.

Example

/* Zebra-stripe a table */
tr:nth-child(even) { background: #f5f5f5; }

/* Style a card that contains an image */
.card:has(img) { padding-top: 0; }

/* Low-specificity reset that is easy to override */
:where(ul, ol) { margin: 0; padding: 0; }

Everything runs in your browser; nothing you search is uploaded.