Combinators & Attribute Selectors

Combinators select elements based on their relationship to other elements — inside them, directly inside, or next to them. Attribute selectors match elements by their attributes and values. Together they let you style precisely without adding a class to everything.

Descendant combinator (space)

Try it yourself
Result

.article a matches any <a> anywhere inside .article, at any depth.

Child combinator (>)

Try it yourself
Result

> matches only direct children, not grandchildren. Use it when nested structures would otherwise inherit styles they shouldn't.

Next-sibling combinator (+)

Try it yourself
Result

A + B matches B when it comes immediately after A, with the same parent.

Subsequent-sibling combinator (~)

Try it yourself
Result

A ~ B matches every B sibling that comes anywhere after A.

Combinator summary

SelectorMatches
A BB anywhere inside A
A > BB that is a direct child of A
A + BB immediately after A
A ~ BAny B after A, same parent

Combinators only look downwards and forwards. To style a parent based on its children, or an element based on what comes after it, use :has() (lesson 43).

Attribute selectors

Try it yourself
Result

Matching parts of a value

Try it yourself
Result
SelectorMatches when the attribute…
[attr]exists
[attr="v"]equals v exactly
[attr^="v"]starts with v
[attr$="v"]ends with v
[attr*="v"]contains v anywhere
[attr~="v"]contains the word v in a space-separated list
[attr|="v"]is v or starts with v- (language codes)
[attr="v" i]case-insensitive match

Styling by state attributes

Attribute selectors pair naturally with ARIA and data attributes, keeping visual state in sync with accessible state:

Try it yourself
Result

Keep selectors short

Long chains like body div.main ul li a span are fragile — any change to the HTML breaks them — and hard to override. Prefer a single meaningful class, with at most one or two levels of combinators.

Try it yourself

Try it yourself
Result