Skip to content
AgileLogics
5 min read

Combinators

Prerequisites: Basic selectors

Combinators select elements by their relationship to other elements in the DOM tree.

Combinator Example Selects
descendant (space) nav a every a anywhere inside a nav
child > ul > li lis that are direct children of a ul
next sibling + h2 + p a p immediately after an h2
subsequent sibling ~ h2 ~ p every p after an h2, with the same parent
<style>
  .menu a { color: blue; }
  .menu > li { font-weight: bold; }
  h2 + p { font-size: 1.25rem; }
  h2 ~ p { color: gray; }
</style>
<ul class="menu">
  <li><a href="/">Home</a>
    <ul>
      <li><a href="/team">Team</a></li>
    </ul>
  </li>
</ul>
<h2>Title</h2>
<p id="p1">First paragraph</p>
<p id="p2">Second paragraph</p>
<script>
  const show = sel => {
    const s = getComputedStyle(document.querySelector(sel));
    console.log(sel.padEnd(22), s.color, s.fontWeight, s.fontSize);
  };
  show(".menu > li");
  show(".menu li li");
  show(".menu li li a");
  show("#p1");
  show("#p2");
</script>
.menu > li             rgb(0, 0, 0) 700 16px
.menu li li            rgb(0, 0, 0) 700 16px
.menu li li a          rgb(0, 0, 255) 700 16px
#p1                    rgb(128, 128, 128) 400 20px
#p2                    rgb(128, 128, 128) 400 16px
  • Both links are blue: .menu a reaches any depth.
  • The nested li is bold too, even though .menu > li only matches the outer one — font-weight is inherited from its bold parent. Selectors pick elements; inheritance then passes some values down.
  • The first paragraph after the h2 is larger; both are gray.

Keep selectors short

body div.content ul.list > li a works, but it's fragile (it breaks when the HTML changes) and hard to override. Prefer a class on the thing you want to style: .list-link.

Practice

Style only the paragraphs that are direct children of an article, and remove the top margin from any element that immediately follows an h1.

Show solution
article > p {
  line-height: 1.7;
}

h1 + * {
  margin-top: 0;
}