Комбинаторы: потомок, дочерний, соседний

Комбинаторы CSS задают отношения между селекторами: пробел выбирает всех потомков, > — только прямых детей, + — ближайшего следующего соседа, ~ — всех следующих братьев.

Зачем нужно

Без комбинаторов приходится добавлять классы к каждому элементу. Комбинаторы позволяют точечно стилизовать элементы по их положению в DOM без лишней разметки — это ключ к чистому CSS для компонентов с предсказуемой структурой.

Где используется

  • Стилизация первого/следующего элемента в списке (li + li)
  • Стили для прямых детей контейнера (> .item)
  • Состояния форм: метка после чекбокса (:checked + label)
  • Уточнение области применения стилей без добавления классов

Четыре комбинатора

Пробел — потомок (descendant combinator)

/* Все <a> внутри .nav, на любом уровне вложенности */
.nav a {
  color: white;
  text-decoration: none;
}

> — дочерний (child combinator)

/* Только прямые дочерние <li> элементы .menu */
.menu > li {
  display: inline-block;
}
/* Вложенные <li> в подменю — не затронуты */

+ — смежный сосед (adjacent sibling combinator)

/* <p> сразу после <h2> */
h2 + p {
  font-size: 1.1rem;
  color: #555;
}

/* Чекбокс + метка */
input[type="checkbox"]:checked + label {
  font-weight: bold;
  color: green;
}

~ — общий сосед (general sibling combinator)

/* Все <p> после <h2> на том же уровне */
h2 ~ p {
  margin-left: 16px;
}

Практические примеры

Отступ между элементами списка (lobotomized owl)

/* Добавить отступ у всех элементов кроме первого */
.list > li + li {
  margin-top: 8px;
}
/* Лучше использовать gap, если доступен */

Форма: метка выделяется при фокусе на поле

input:focus + label {
  color: var(--color-primary);
}
<!-- Порядок важен: input перед label -->
<input type="text" id="name">
<label for="name">Имя</label>

Только прямые дочерние карточки

.grid > .card {
  border: 1px solid #eee;
  border-radius: 8px;
}
/* Вложенные .card внутри других .card — не затронуты */

Частые ошибки

  1. Пробел vs >.nav a выбирает все вложенные ссылки включая подменю; .nav > a — только прямых детей.
  2. + работает только вперёд — нет CSS-способа выбрать предыдущий элемент; для этого нужен :has.
  3. Порядок в +input + label работает только если label идёт в HTML после input; порядок в DOM критичен.

Связанные темы

Ресурсы