CSS Combinators

A combinator connects two selectors and defines the relationship between them. Instead of styling all paragraphs on a page, you can target only paragraphs that are inside a specific section, or only the paragraph that comes right after a heading. Combinators give you that precision.

CSS has four combinators. Each one describes a different type of relationship in the HTML family tree.

Understanding the HTML Family Tree

HTML elements have family relationships — parent, child, sibling, ancestor, and descendant. Combinators use these relationships to target elements precisely.

DIAGRAM — HTML Family Tree:

<div>                    ← Parent (ancestor)
  <section>              ← Child of div
    <h2>Title</h2>      ← Grandchild of div, child of section
    <p>First para</p>   ← Sibling of h2
    <p>Second para</p>  ← Sibling of h2, sibling of first p
  </section>
</div>

1. Descendant Combinator (space)

A space between two selectors targets all matching elements anywhere inside the first element, at any depth.

Syntax: A B

div p {
  color: blue;
}

This targets every <p> inside a <div>, whether it is a direct child or deeply nested.

DIAGRAM — Descendant Combinator:

<div>
  <p>✅ Selected — direct child</p>
  <section>
    <p>✅ Selected — nested deeper</p>
    <article>
      <p>✅ Selected — even deeper</p>
    </article>
  </section>
</div>

<p>❌ Not selected — outside the div</p>

Real Use Case

/* Style all links inside the navigation only */
nav a {
  text-decoration: none;
  font-weight: bold;
}

Links inside <nav> get styled. Links in a footer or article do not.

2. Child Combinator (>)

The > symbol targets only direct children — one level down, not deeper.

Syntax: A > B

ul > li {
  list-style: square;
}
DIAGRAM — Child Combinator:

<ul>
  <li>✅ Selected — direct child</li>
  <li>✅ Selected — direct child
    <ul>
      <li>❌ Not selected — grandchild, not direct child</li>
    </ul>
  </li>
</ul>

Real Use Case

/* Style only the top-level nav items, not dropdown sub-items */
.menu > li {
  display: inline-block;
  padding: 10px;
}

3. Adjacent Sibling Combinator (+)

The + symbol targets the element that comes immediately after the first element, and both must share the same parent.

Syntax: A + B

h2 + p {
  font-size: 1.1rem;
  color: gray;
}
DIAGRAM — Adjacent Sibling Combinator:

<section>
  <h2>Article Title</h2>
  <p>✅ Selected — immediately after h2</p>
  <p>❌ Not selected — not immediately after h2</p>
  <p>❌ Not selected</p>
</section>

Real Use Case

/* Remove margin from the paragraph right after a heading */
h2 + p {
  margin-top: 0;
}

/* Style a label that comes right after a checked checkbox */
input:checked + label {
  font-weight: bold;
  color: green;
}

4. General Sibling Combinator (~)

The ~ symbol targets all matching siblings that come after the first element, not just the one immediately next.

Syntax: A ~ B

h2 ~ p {
  color: gray;
}
DIAGRAM — General Sibling Combinator:

<section>
  <h2>Title</h2>
  <p>✅ Selected — sibling after h2</p>
  <div>Divider</div>
  <p>✅ Selected — also a sibling after h2</p>
  <p>✅ Selected — also a sibling after h2</p>
</section>

<p>❌ Not selected — different parent</p>

Real Use Case

/* When a checkbox is checked, show all sibling content panels */
input:checked ~ .panel {
  display: block;
}

All Four Combinators Side by Side

DIAGRAM — Combinator Comparison:

HTML:
<div>
  <p>A</p>         ← direct child
  <section>
    <p>B</p>       ← nested descendant
  </section>
</div>
<p>C</p>           ← sibling of div
<p>D</p>           ← sibling of div

Selector         │ Selects
─────────────────┼────────────
div p            │ A and B (all descendants)
div > p          │ A only (direct child)
div + p          │ C only (immediately after div)
div ~ p          │ C and D (all siblings after div)

Combining Combinators

You can chain multiple combinators in one selector.

/* Paragraphs that are children of articles inside main */
main article > p {
  line-height: 1.8;
}

/* The label right after a required input inside a form */
form input[required] + label {
  color: red;
}

Performance Note

Browsers read CSS selectors from right to left. The rightmost part is matched first. For example, div p finds all <p> elements first, then checks if they are inside a <div>. Keeping selectors short and avoiding deep nesting makes them faster to process.

Quick Reference

CombinatorSymbolSelects
DescendantspaceAll matching elements inside A (any depth)
Child>Direct children of A only
Adjacent Sibling+Element immediately after A (same parent)
General Sibling~All matching siblings after A (same parent)

Combinators make your CSS more targeted without needing extra classes. A single well-chosen combinator replaces several unnecessary class names and keeps your HTML clean.

Leave a Comment

Your email address will not be published. Required fields are marked *