All cheat sheets

CSS Selectors Cheat Sheet

Quick reference for CSS selectors: basic, attribute, pseudo-classes, pseudo-elements, and combinators.

Languages
css
selectors
styling

CSS selectors are patterns that target HTML elements for styling. The CSS Selectors Level 3 / 4 specifications (see W3C Selectors Level 3 and the MDN reference) define everything below. Modern browsers support all of these; older IE-specific selectors (*+*, :-ms-*) are omitted.

Basic selectors

Table
SelectorMeaningExample
*Universal — any element* { box-sizing: border-box; }
divType selector — by tag nameh1 { color: teal; }
.clsClass.btn { padding: .5rem 1rem; }
#idID (one per document)#app { margin: 0; }
A, BSelector list — match any of the selectorsh1, h2, h3 { font-family: serif; }

Multiple classes stack: .btn.primary matches an element with both classes.

Combinators

Combinators describe the relationship between two simple selectors.

Table
CombinatorNameMeaningExample
A BDescendantB anywhere inside Aarticle p
A > BChildB is a direct child of Aul > li
A + BAdjacent siblingB immediately follows A as a siblingh1 + p
A ~ BGeneral siblingAny B sibling that follows Ah1 ~ p
css
/* only direct children */
.nav > li { padding: 0 .5rem; }

/* first paragraph after each h2 */
h2 + p { margin-top: 0; }

/* every sibling paragraph after an h1 */
h1 ~ p { font-size: .95rem; }

Attribute selectors

Table
SelectorMeaning
[attr]Element has the attribute (any value)
[attr="v"]Value equals v (exact, case-sensitive)
[attr~="v"]Value is a whitespace-separated word list containing v
`[attr="v"]`
[attr^="v"]Value starts with v
[attr$="v"]Value ends with v
[attr*="v"]Value contains v
[attr="v" i]Case-insensitive match (add s for case-sensitive default)
css
input[type="email"] { /* ... */ }
a[href^="https://"] { /* ... */ }
img[src$=".svg"]     { /* ... */ }
a[href*="example"]   { /* ... */ }
[data-theme="dark" i] { /* ... */ }

Pseudo-classes

A pseudo-class targets a state or structural position. Pseudo-classes are written with a single colon (:).

Table
Pseudo-classSelects
:hoverElement under the pointer
:focusElement has keyboard focus
:focus-visibleElement has keyboard focus that the UA determines is appropriate
:activeElement being activated (e.g. mouse-down)
:visited / :linkVisited / unvisited <a> / <area> links
:first-childFirst child of its parent
:last-childLast child of its parent
:only-childSole child of its parent
:nth-child(n)Nth child (1-indexed; 2n, odd, even)
:nth-last-child(n)Nth child counting from the end
:first-of-typeFirst sibling of its type
:last-of-typeLast sibling of its type
:nth-of-type(n)Nth sibling of its type
:only-of-typeSole sibling of its type
:not(s)Negation — elements not matched by selector s
:is(s)Matches if any selector in s matches
:where(s)Like :is but contributes 0 specificity
:has(s)Matches if the element contains a descendant matching s
:rootThe document root (<html>)
:emptyElement with no children (including text nodes)
:checkedChecked checkbox / radio
:disabled / :enabledForm element state
:required / :optionalForm validation attribute
:valid / :invalidElement meets / fails its constraints
:targetElement whose id matches the URL fragment
:lang(en)Element with language en
css
/* every other row in a table */
tr:nth-child(2n) { background: #f4f4f4; }

/* any direct child that is not a span */
li:not(span) { /* ... */ }

/* card containing an image */
.card:has(img) { grid-template-rows: auto 1fr; }

Pseudo-elements

Pseudo-elements style a specific part of an element. They are written with two colons (::); single-colon legacy aliases (:before, :after) still work.

Table
Pseudo-elementTargets
::beforeGenerated content before the element's content
::afterGenerated content after the element's content
::first-lineFirst formatted line of a block
::first-letterFirst letter of the first formatted line
::placeholderPlaceholder text of an input
::selectionThe portion currently highlighted by the user
::markerThe bullet or number of a list item
css
.note::before { content: "ℹ "; color: teal; }
input::placeholder { color: #999; }

Specificity

Specificity decides which rule wins when two selectors match the same element. It is computed as a 4-tuple (inline, id, class/attr/pseudo-class, element/pseudo-element). Higher components dominate lower ones.

Table
ComponentExampleWeight
Inline style="..."<div style="...">1,0,0,0
ID selector#header0,1,0,0
Class, attribute, pseudo-class.btn, [type="text"], :hover0,0,1,0
Element, pseudo-elementh1, ::before0,0,0,1
Universal selector*0,0,0,0

Quick calculation:

css
#nav .item.active a:hover   /* id (1) class (3) element (1) -> (0,1,3,1) */
ul#nav li.active            /* id (1) class (1) element (2) -> (0,1,1,2) */

The first rule wins on specificity. Tied selectors defer to source order.

:is() and :where() and specificity

:is(a, b, c) matches any of its arguments, and its specificity is the highest specificity of its arguments. :where(...) does the same but contributes zero specificity — useful for portable selectors in libraries.

css
:is(#main, .sidebar) p    /* specificity 1,0,0,1 — like #main p */
:where(#main, .sidebar) p /* specificity 0,0,0,1 — like p */

!important overrides specificity but is reserved for last-resort cases (utility classes, accessibility fixes).

References