CSS Selectors Cheatsheet

Every selector type with examples — from basics to :has()

Basic Selectors

SelectorExampleSelects
ElementpAll <p> elements
Class.cardElements with class="card"
ID#headerElement with id="header"
Universal*All elements
Attribute[type="email"]Elements with type="email"

Combinators

CombinatorExampleSelects
Descendant (space).nav aAny <a> inside .nav (any depth)
Child (>).nav > aDirect <a> children of .nav only
Adjacent sibling (+)h2 + pFirst <p> immediately after <h2>
General sibling (~)h2 ~ pAll <p> after <h2> (same parent)
/* Only direct children */ .menu > li { list-style: none; } /* First paragraph after a heading */ h2 + p { font-size: 1.1rem; margin-top: 8px; }

Pseudo-Classes

User Action

a:hover { color: #4f46e5; } /* mouse over */ a:active { color: #3730a3; } /* being clicked */ a:focus { outline: 2px solid; } /* keyboard focus */ a:visited { color: #7c3aed; } /* previously visited */ input:focus-visible { outline: 2px solid #6366f1; } /* keyboard focus only */

Structural

li:first-child { font-weight: bold; } li:last-child { border-bottom: none; } li:nth-child(odd) { background: #f8fafc; } li:nth-child(3n) { color: red; } /* every 3rd */ li:nth-child(n+4) { opacity: 0.6; } /* 4th and beyond */ tr:nth-of-type(even) { background: #f1f5f9; } p:only-child { margin: 0; } div:empty { display: none; }

Form States

input:required { border-left: 3px solid #6366f1; } input:disabled { opacity: 0.5; cursor: not-allowed; } input:checked { accent-color: #6366f1; } input:valid { border-color: #10b981; } input:invalid { border-color: #ef4444; } input:placeholder-shown { background: #f8fafc; }

Negation and Matching

/* Everything except .special */ .item:not(.special) { opacity: 0.8; } /* Matches any of these selectors */ :is(h1, h2, h3) { font-weight: 700; } /* Same as :is() but with zero specificity */ :where(h1, h2, h3) { margin-top: 1em; } /* Select multiple nth-children at once */ :nth-child(2 of .highlight) { background: yellow; }

The :has() Selector (Parent Selector)

The most powerful selector addition in years. It selects elements based on their descendants:

/* Card that contains an image */ .card:has(img) { padding: 0; } /* Form group with an invalid input */ .form-group:has(input:invalid) { border-color: #ef4444; } /* h2 followed by a paragraph (previous-sibling selector!) */ h2:has(+ p) { margin-bottom: 8px; } /* Page that has a modal open */ body:has(.modal.open) { overflow: hidden; }

Supported in Chrome 105+, Safari 15.4+, Firefox 121+. Safe to use in production.

Pseudo-Elements

/* Insert content before/after */ .required::before { content: "*"; color: red; } blockquote::before { content: "\201C"; font-size: 2rem; } /* opening quote */ /* Style the first line or letter */ p::first-line { font-weight: 600; } p::first-letter { font-size: 2rem; float: left; } /* Style text selection */ ::selection { background: #6366f1; color: white; } /* Style placeholder text */ input::placeholder { color: #94a3b8; } /* Style scrollbar (webkit) */ ::-webkit-scrollbar { width: 8px; } ::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }

Attribute Selectors

SelectorMatches
[href]Has the attribute (any value)
[type="submit"]Exact value match
[class~="card"]Word in space-separated list
[href^="https"]Starts with "https"
[src$=".png"]Ends with ".png"
[data-type*="nav"]Contains "nav" anywhere
[lang|="en"]Exactly "en" or starts with "en-"
/* External links */ a[href^="http"]:not([href*="zerokit.dev"]) { &::after { content: " ↗"; } } /* File type icons */ a[href$=".pdf"]::before { content: "📄 "; } a[href$=".zip"]::before { content: "📦 "; }

Specificity

Specificity determines which rule wins when multiple rules target the same element. It is calculated as (IDs, Classes, Elements):

SelectorSpecificity
p(0, 0, 1)
.card(0, 1, 0)
#header(1, 0, 0)
.card .title(0, 2, 0)
#nav .link:hover(1, 2, 0)
div.card > p.text(0, 2, 2)

:where() has zero specificity — useful for defaults that are easy to override. :is() takes the specificity of its most specific argument.

Frequently Asked Questions

How does CSS specificity work?
Specificity is a three-part score: (IDs, Classes, Elements). #nav = (1,0,0). .active = (0,1,0). div = (0,0,1). Higher scores win. Equal scores: last rule in source order wins. !important beats everything but should be avoided. :where() has zero specificity.
What is the difference between :nth-child and :nth-of-type?
:nth-child(n) counts among ALL siblings. :nth-of-type(n) counts among siblings of the same element type. p:nth-child(2) matches a <p> only if it is the 2nd child overall. p:nth-of-type(2) matches the 2nd <p> regardless of other elements.
What does :has() do?
:has() is a parent selector — it selects an element based on its contents. .card:has(img) selects cards with images. h2:has(+ p) selects h2 followed by p (previous-sibling selector). Supported in all major browsers.

Related Tools