CSS Anatomy - Symbols, Structure & Terminology
A reference for all the punctuation, prefixes, and structural elements of CSS.
The anatomy of a CSS rule
| Term | What it is | Example |
|---|---|---|
| Rule | A selector + declaration block together | .card { color: red; } |
| Selector | What to target | .card:hover > .title |
| Declaration block | Everything between { } | { color: red; margin: 0; } |
| Declaration | One property-value pair | color: red; |
| Property | What to style | color |
| Value | How to style it | red |
Selector anatomy
#main .card :hover > .title ::before [data-v]
├──┤ ├───┤ ├────┤ │ ├────┤ ├──────┤ ├──────┤
ID CLASS PSEUDO COMB CLASS PSEUDO ATTRIBUTE
CLASS INATOR ELEMENT SELECTOR
| Selector type | Syntax | Example | Specificity column |
|---|---|---|---|
| Universal | * | * { margin: 0; } | (0, 0, 0) |
| Element (type) | element | h1, div, p | C (elements) |
| Class | .name | .card, .active | B (classes) |
| ID | #name | #main, #header | A (IDs) |
| Attribute | [attr] or [attr=val] | [type="email"] | B (classes) |
| Pseudo-class | :name | :hover, :focus, :not() | B (classes) |
| Pseudo-element | ::name | ::before, ::after | C (elements) |
CSS symbols - what each punctuation means
. Dot - class selector
Selects elements by class name. .card matches <div class="card">.
# Hash - ID selector
Selects a single element by ID. #main matches <div id="main">. Highest specificity of any selector.
: Single colon - pseudo-class
Selects an element in a particular state or position. The element itself exists in the DOM - the pseudo-class is a condition on it.
:hover /* mouse is over it */
:focus /* it has keyboard focus */
:first-child /* it's the first child of its parent */
:not(.x) /* it does NOT match .x */
:has(.x) /* it contains .x */
:is(.a, .b) /* it matches .a OR .b */
:where(.a) /* same as :is but zero specificity */
:nth-child(2) /* it's the 2nd child */
:checked /* checkbox/radio is checked */
:invalid /* form field fails validation */
:: Double colon - pseudo-element
Targets something the browser generates that doesn't exist as a real DOM element. You're styling a "virtual" piece of the element.
::before /* generated content before the element's content */
::after /* generated content after the element's content */
::placeholder /* placeholder text in inputs */
::selection /* text the user has highlighted */
::view-transition-old(name) /* snapshot of old state during view transition */
::view-transition-new(name) /* snapshot of new state during view transition */
: vs :: - the mental model: Single colon = state/condition of a real element. Double colon = a generated virtual element that doesn't exist in your HTML. Historically, :before worked (single colon), but the double colon is the correct modern syntax.
-- Double hyphen - custom property (variable) or custom name
The -- prefix marks something as user-defined. The spec reserves this prefix so your names never collide with current or future CSS properties.
/* Custom properties (variables) */
--color-primary: #3a86ff; /* declaration */
color: var(--color-primary); /* usage */
/* Custom names for other features */
anchor-name: --my-button; /* anchor positioning */
view-transition-name: --hero; /* view transitions (-- optional here) */
@function --double(--value) {} /* custom function name */
@property --size {} /* registered property */
@ At-sign - at-rule
Introduces a structural rule or directive - something that controls how CSS is applied rather than styling an element directly.
/* Conditional rules - apply styles under conditions */
@media (width < 768px) { } /* viewport condition */
@container (min-width: 400px) { } /* container condition */
@supports (display: grid) { } /* feature detection */
/* Structural rules - define CSS structure */
@layer reset, base, components; /* cascade layer order */
@layer base { } /* add styles to a layer */
@import url("file.css"); /* import another stylesheet */
/* Definitions - define reusable things */
@keyframes spin { } /* animation sequence */
@function --name() { } /* custom function */
@property --size { } /* registered custom property */
@font-face { } /* custom font */
/* Configuration */
@view-transition { navigation: auto; } /* opt into view transitions */
@position-try --below { } /* anchor positioning fallback */
@scope (.card) { } /* style scoping */
@ = "meta-level CSS." Regular rules say "style this element like that." At-rules say "here's a condition/structure/definition that governs how other rules work." They never directly style an element - they create context for rules that do.
& Ampersand - parent selector (in nesting)
Inside a nested rule, & represents the outer/parent selector. Used to compose selectors.
.card {
& .title { } /* → .card .title (descendant) */
&:hover { } /* → .card:hover (pseudo-class on parent) */
&.featured { } /* → .card.featured (compound - same element) */
}
> + ~ (space) - combinators
Combinators define the relationship between two selector parts:
| Combinator | Means | Example |
|---|---|---|
(space) | Descendant (any depth) | .card .title - .title anywhere inside .card |
> | Direct child only | .card > .title - .title that's a direct child of .card |
+ | Adjacent sibling (next) | h2 + p - the first p immediately after an h2 |
~ | General sibling (any after) | h2 ~ p - any p that comes after an h2 (same parent) |
! - !important
Placed after a value to escalate it above normal cascade resolution. Jumps to a higher tier in the cascade (above layers and specificity).
color: red !important; /* wins over any normal declaration regardless of specificity */
[] Square brackets - attribute selector
[data-v] /* has the attribute at all */
[type="email"] /* attribute equals value */
[class~="card"] /* attribute word list contains "card" */
[href^="https"] /* attribute starts with "https" */
[src$=".png"] /* attribute ends with ".png" */
[data*="user"] /* attribute contains "user" anywhere */
Quick symbol cheat sheet
| Symbol | Context | Meaning |
|---|---|---|
. | Selector | Class |
# | Selector | ID |
: | Selector | Pseudo-class (state/condition) |
:: | Selector | Pseudo-element (generated content) |
-- | Name prefix | User-defined (custom property, function, anchor, etc.) |
@ | Rule start | At-rule (structural/conditional/definition) |
& | Nesting | Parent selector reference |
> | Selector | Direct child combinator |
+ | Selector | Adjacent sibling combinator |
~ | Selector | General sibling combinator |
(space) | Selector | Descendant combinator |
[] | Selector | Attribute selector |
! | Value suffix | !important escalation |
* | Selector | Universal selector (match anything) |