Table of Contents
05. State Selectors — Targeting Elements by Their Conditions
—Part of CSS Primer for the AI Era — Selectors
State selectors let us target elements
based on their current condition
— whether they are
hovered,
focused,
checked,
active,
visited,
empty,
or in some other temporary or structural state.
Where attribute selectors describe properties,
'state selectors' describe moments.
They help us style elements
not just by what they are,
but by what they are doing right now.
1. What State Selectors Are
State selectors are pseudo‑classes* that
match elements when
they enter a particular condition.
These conditions may be:
- user‑driven
- browser‑driven
- form‑driven
- structural
- temporary
- interactive
State selectors let us adjust
our styling
as an element moves through
different conditions..
* NOTE:
A real CSS class is written directly in the HTML markup.
A pseudo‑class, however, is virtual
— the browser applies it automatically when an element enters a particular condition or state.
We write pseudo‑classes using a single colon (:)
followed by the name of the state we want to target.
2. User‑Interaction States
These states reflect how a user interacts with an element.
:hover — when the pointer is over the element
button:hover
→ We use this to provide gentle feedback —
a visual whisper that says “yes, this is interactive.”
:focus — when the element is focused
input:focus
→ Essential for accessibility.
Focus is how keyboard and assistive‑technology users navigate.
:active — when the element is being pressed
button:active
→ A brief, tactile moment — the press itself.
3. Form‑Related States
Forms are full of meaningful conditions.
:checked — for checkboxes and radio buttons
input[type=“checkbox”]:checked
→ A simple, powerful way to style selected options.
:disabled — when the element cannot be interacted with
button:disabled
→ This expresses state without relying on classes.
:required and :optional
input:required
→ We can style fields based on whether they must be filled.
:valid and :invalid
input:invalid
→ The browser’s built‑in validation becomes a styling hook.
4. Link States
Links have their own lifecycle.
:link — unvisited links
a:link← example
:visited — links the user has already visited
a:visited ← example
Browsers protect privacy here, so styling options are intentionally limited.
Example of
Styling Unvisited Links with
a:link
HTML
<a href="https://example.com">Visit Example</a> <a href="/local-page">Local Page</a>
CSS
a:link { color: #0645ad; /* classic unvisited link color */ text-decoration: underline; }
What this does:
The rule applies only to links the visitor has not yet visited.
Once the link is visited, the browser switches to a:visited instead.
This gives us a clean way to differentiate unvisited and visited states without adding classes.
5. Structural States
Some states describe the element’s position or content.
:first-child and :last-child
li:first-child← example.
Targets the very first child inside its parent container (such as a <ul> or <ol>).
:empty — elements with no children and no text
div:empty← example
Useful for layout gaps or placeholder styling.
:not() — negation
button:not([disabled])← example.
This lets us express intent by exclusion.
6. Why State Selectors Matter
State selectors let us respond to:
- interaction
- validation
- accessibility
- structure
- temporary conditions
- browser logic
They help us build interfaces that feel alive, responsive, and intentional —
without adding extra classes or JavaScript.
They also give us a vocabulary for guiding AI:
“Style this element when it is in this condition.”
This is the heart of state‑based styling.
7. When We Use State Selectors
We reach for state selectors when:
- the browser already knows the condition
- the condition is temporary
- the condition is user‑driven
- the condition is structural
- adding a class would be redundant
Examples:
:hoverfor interaction:focusfor accessibility:checkedfor toggles:invalidfor validation:emptyfor layout cleanup
These selectors let us style based on behavior,
not just structure.
8. When We Avoid Them
We avoid state selectors when:
- the condition is not expressible as a browser state
- the condition depends on logic, not structure
- the condition is long‑lived and should be expressed semantically
- a class would be clearer
For example, “selected tab” is usually a class, not a pseudo‑class.
AI‑Steering Cue:
“Use a state selector — style the element when it enters this condition.”
This helps us guide AI
toward behavior‑based
styling rather than structural guessing.
- Suggested Next Reading: Pseudo‑elements — Styling Parts of an Element
Tony de Araujo —New York | Lisbon
