CSS Selector Cheat Sheet

Search common CSS selectors, combinators, pseudo-classes, and pseudo-elements, or inspect selector specificity before you ship a rule.

Last updated: August 2026 | By Workshelve Team

Basic

Universal selector

*
* { box-sizing: border-box; }

Matches every element. Useful for resets, but keep heavy declarations out of universal rules.

Basic

Type selector

button
button { cursor: pointer; }

Matches every element with that tag name.

Basic

Class selector

.card
.card { border-radius: 12px; }

Matches elements with a class. This is the usual workhorse for component styling.

Basic

ID selector

#app
#app { min-height: 100vh; }

Matches a single ID. High specificity makes IDs harder to override.

Attributes

Attribute presence

[disabled]
button[disabled] { opacity: 0.5; }

Matches elements that have the attribute, regardless of its value.

Attributes

Attribute exact value

[type="email"]
input[type="email"] { min-width: 18rem; }

Matches an attribute value exactly.

Attributes

Attribute starts with

[href^="https"]
a[href^="https"] { color: #0ea5e9; }

Useful for matching URL prefixes, file naming conventions, or data attributes.

Attributes

Attribute ends with

[src$=".svg"]
img[src$=".svg"] { image-rendering: auto; }

Common for file extension checks.

Attributes

Attribute contains

[class*="icon"]
[class*="icon"] { flex-shrink: 0; }

Powerful but broad. Prefer explicit classes when you control the markup.

Combinators

Descendant combinator

.card .title
.card .title { font-weight: 700; }

Matches nested descendants at any depth.

Combinators

Child combinator

.tabs > button
.tabs > button { border-radius: 999px; }

Matches direct children only.

Combinators

Adjacent sibling

h2 + p
h2 + p { margin-top: 0.5rem; }

Matches the first matching sibling immediately after another element.

Combinators

General sibling

h2 ~ p
h2 ~ p { color: #475569; }

Matches later siblings that share the same parent.

Pseudo-classes

Hover state

:hover
.button:hover { background: #0284c7; }

Applies when a pointing device hovers the element.

Pseudo-classes

Keyboard focus

:focus-visible
.button:focus-visible { outline: 3px solid #38bdf8; }

Preferred for visible keyboard focus without forcing focus rings on most mouse clicks.

Pseudo-classes

Checked control

:checked
input:checked + label { font-weight: 700; }

Matches checked checkboxes, radios, and selected options.

Pseudo-classes

Nth child

:nth-child(2n)
tr:nth-child(2n) { background: #f8fafc; }

Matches elements by sibling position. 2n is every even item.

Pseudo-classes

Negation

:not(.active)
.tab:not(.active) { opacity: 0.7; }

Excludes selectors. The argument still contributes specificity in modern CSS.

Pseudo-classes

Selector list matcher

:is(h1, h2, h3)
:is(h1, h2, h3) a { text-decoration: none; }

Groups selector alternatives. Its specificity is the highest specificity argument.

Pseudo-classes

Zero-specificity matcher

:where(section, article)
:where(section, article) > h2 { margin-block-start: 0; }

Matches like :is(), but contributes zero specificity.

Pseudo-elements

Before pseudo-element

::before
.badge::before { content: ""; }

Creates a generated child-like pseudo-element before content.

Pseudo-elements

After pseudo-element

::after
.link::after { content: " ->"; }

Creates generated content after the element content.

Pseudo-elements

Placeholder text

::placeholder
input::placeholder { color: #94a3b8; }

Styles placeholder text inside form fields.

How CSS Selectors Work

CSS selectors choose which elements a rule applies to. Simple selectors target element names, classes, IDs, or attributes. Combinators describe relationships such as descendants, direct children, and siblings.

Pseudo-classes select states or structural positions, such as :hover, :checked, or :nth-child(2n). Pseudo-elements such as ::before and ::after target generated or sub-element-like parts of an element.

This tool is not bidirectional because it is a reference and analyzer. There is no single reverse conversion from CSS behavior back to the selector that caused it; cascade, order, inheritance, media queries, and JavaScript state all matter.

Specificity Basics

1. ID selectors add to the first specificity column.
2. Classes, attributes, and pseudo-classes add to the second column.
3. Type selectors and pseudo-elements add to the third column.
4. :is(), :not(), and :has() take the specificity of their most specific argument.
5. :where(...) and its arguments contribute zero specificity.
6. :nth-child(... of selector) adds one pseudo-class plus the most specific selector after of.
.card
0, 1, 0
#app .card
1, 1, 0
button:hover
0, 1, 1
:where(section) .title
0, 1, 0

Worked Example: A Stateful Card Heading

Inspect this selector:

Selector
main#app .card[data-state="open"]:hover > h2::before
Count
ID: 1, class/attribute/pseudo-class: 3, type/pseudo-element: 3
Meaning

It targets a generated marker before an h2 that is a direct child of a hovered, open card inside the element with ID app.

CSS Selector FAQ

What selector should I use most often?

Class selectors are usually the best default because they are reusable, readable, and easier to override than IDs.

Why avoid IDs for styling?

IDs have high specificity. They can make later overrides awkward unless you add even more specificity.

What is the difference between > and a space?

A space matches descendants at any depth. The > combinator matches only direct children.

When should I use :where()?

:where() is useful for broad defaults because it contributes zero specificity, making component styles easier to override.

Does :not() add specificity?

The :not() pseudo-class itself does not add specificity. Its specificity is replaced by the most specific selector in its argument list.

What is a pseudo-element?

A pseudo-element targets a generated or element-part-like piece, such as ::before, ::after, or ::placeholder.

Is the specificity analyzer a complete CSS parser?

No. It implements the specificity rules used by the selectors shown here, including functional pseudo-classes, and rejects syntax it cannot safely analyze rather than guessing.

Why is this not bidirectional?

Rendered styles come from selectors plus cascade, order, inheritance, and runtime state, so behavior cannot be converted back into one exact selector.

Related Tools