Skip to main content
Syllabus
On this page

CSS Combinators: Descendant, Child, Adjacent & General Sibling

Badar KhalilUpdated September 29, 2026 4 min read

CSS Combinators: Selecting Elements by Relationship

CSS combinators let you select elements based on their relationship in the HTML tree: parent, child, ancestor, descendant and sibling. Instead of adding classes to every element, combinators let you style structure precisely. There are four main combinators: the descendant (space), the child (>), the adjacent sibling (+) and the general sibling (~).

Understanding the DOM Family Tree

  • Parent - an element directly containing another.
  • Child - an element directly inside a parent.
  • Ancestor - a parent, grandparent and so on, up the tree.
  • Descendant - a child, grandchild and so on, down the tree.
  • Siblings - elements that share the same parent.

1. Descendant Combinator (Space)

Syntax: ancestor descendant. It matches the second element anywhere inside the first, no matter how deeply nested.

  • nav a matches every link inside a nav, even links inside nested lists.
  • It is the most common combinator, but also the easiest to overuse because it can match more than you intend.

2. Child Combinator (>)

Syntax: parent > child. It matches only direct children, not grandchildren.

  • ul > li selects only the list items of that list, not the items in nested lists.
  • Use it for precision and to avoid unwanted inheritance in nested components such as menus.

3. Adjacent Sibling Combinator (+)

Syntax: first + second. It matches the second element only if it comes immediately after the first, and both share the same parent.

  • h2 + p selects the first paragraph directly after each h2.
  • Classic use: spacing rules, such as .item + .item { margin-top: 1rem; } (a lightweight alternative to adding margins to the last child).

4. General Sibling Combinator (~)

Syntax: first ~ second. It matches every following sibling of the first element, not only the next one.

  • h2 ~ p selects all paragraphs that follow an h2 within the same parent.
  • Famous use: the checkbox hack, input:checked ~ .menu { display: block; }, which toggles UI with no JavaScript.

Important Limitation: CSS Looks Forward Only

Sibling combinators only select elements after the reference element in the source order. Traditionally CSS could not select a parent or previous sibling. The modern :has() pseudo-class now makes this possible, for example li:has(+ li.active) (see the pseudo-classes lesson).

Comparison Table

CombinatorSymbolExampleMatches
Descendantspacediv pAny p inside div, at any depth
Child>div > pp that is a direct child of div
Adjacent sibling+h2 + pThe p immediately after h2
General sibling~h2 ~ pAll following p siblings of h2

Specificity of Combinators

Combinators themselves add no specificity. The score comes from the selectors they connect. So nav a is (0,0,2), while .nav > .link is (0,2,0). Long chains raise specificity and make styles harder to override, so keep chains short (2 to 3 parts is usually enough).

Combining with Other Selectors

  • .card > h3 + p selects the paragraph right after an h3 that is a direct child of .card.
  • .menu li:not(:last-child) adds a divider to every item except the last.
  • form label + input styles the input right after a label.

Performance and Maintainability

Modern browsers match selectors right to left and handle combinators efficiently, so performance is rarely an issue. The bigger concern is maintainability: deeply nested selectors like body div.main ul li a span are brittle. If your HTML changes, the CSS breaks. Prefer a class on the element when the chain gets long. Native CSS nesting can also help you group related rules clearly.

Common Mistakes

  • Confusing the descendant space with a compound selector (.a .b is not .a.b).
  • Expecting + to work for elements that are not immediate siblings, such as when a wrapper element sits in between.
  • Expecting ~ to select previous siblings.
  • Writing overly long selector chains with high specificity.

Key Takeaways

  • Descendant (space) = any depth; child (>) = direct children only.
  • Adjacent (+) = the very next sibling; general (~) = all following siblings.
  • Combinators add no specificity themselves, but chains do accumulate it.
  • Keep chains short and use classes for clarity.
Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Exercise: Navigation Links OnlyHTML

Make the links that are DIRECT children of the nav orange, but leave the link inside the nested dropdown div unchanged.

Try it Yourself HTML
Output

Press Run to execute.

Show expected output
nav > a { color: orange; }

This is a self-check — compare your result with the expected output above.

Exercise: Style the Sibling After a LabelHTML

Add a green border to the input that comes immediately after a label. Then make every paragraph that follows the h3 (as siblings) gray.

Try it Yourself HTML
Output

Press Run to execute.

Show expected output
label + input { border: 2px solid green; } h3 ~ p { color: gray; }

This is a self-check — compare your result with the expected output above.

Was this page helpful?