Комбинированные селекторы

Время чтения: меньше 5 мин

Кратко

Секция статьи "Кратко"

Иногда при написании стилей мы хотим обратиться к селектору более точно, чем просто по имени класса или тега. Для этого можно использовать различные комбинации.

Группировка: .element1, .element2

Секция статьи "Группировка: .element1, .element2"

Пример

Секция статьи "Пример"

Если нескольким селекторам нужно задать одно и то же правило, то можно написать длинно:

        
          
          h1 {  font-weight: bold;}h2 {  font-weight: bold;}h3 {  font-weight: bold;}
          h1 {
  font-weight: bold;
}

h2 {
  font-weight: bold;
}

h3 {
  font-weight: bold;
}

        
        
          
        
      

А можно перечислить все селекторы через запятую и написать всего одно CSS-правило:

        
          
          h1, h2, h3 {  font-weight: bold;}
          h1, h2, h3 {
  font-weight: bold;
}

        
        
          
        
      

Как пишется

Секция статьи "Как пишется"

Селекторы просто записываются в произвольном порядке через запятую:

        
          
          .selector1,code,#id,[attr="value"] {  color: red;}
          .selector1,
code,
#id,
[attr="value"] {
  color: red;
}

        
        
          
        
      

Если вы перечисляете селекторы через запятую, то правила будут применяться к каждой из групп:

        
          
          .heading span,.block,.wrapper {  color: red;}
          .heading span,
.block,
.wrapper {
  color: red;
}

        
        
          
        
      

Как это понять

Секция статьи "Как это понять"

В примере свойство применится для трёх типов селекторов:

  1. Для всех <span> внутри класса .heading (на любом уровне вложенности);
  2. для всех элементов с классом .block;
  3. для всех элементов с классом .wrapper.

Объединение: .class1.class2

Секция статьи "Объединение: .class1.class2"

Пример

Секция статьи "Пример"
        
          
          .selector.selector_modificator {  color: red;}
          .selector.selector_modificator {
  color: red;
}

        
        
          
        
      

Как пишется

Секция статьи "Как пишется"

Этот приём применим только для классов и атрибутов, потому что только их может быть больше одного. Селекторы записываются слитно. Стили будут применены только к тому элементу, который содержит все перечисленные селекторы.

Как это понять

Секция статьи "Как это понять"

Такое «склеивание» объединяет селекторы в одно правило.

Потомки: .element1 .element2

Секция статьи "Потомки: .element1 .element2"

Пример

Секция статьи "Пример"
        
          
          article h3 {  color: red;}
          article h3 {
  color: red;
}

        
        
          
        
      

Как пишется

Секция статьи "Как пишется"

Селекторы записываются последовательно через пробел.

Как это понять

Секция статьи "Как это понять"

Последовательность селекторов отражает вложенность — каждый следующий селектор должен обязательно находиться на каком-то уровне вложенности в предыдущий селектор.

Непосредственно вложенные: .element1 > .element2

Секция статьи "Непосредственно вложенные: .element1 > .element2"

Пример

Секция статьи "Пример"
        
          
          article > h3 {  color: red}
          article > h3 {
  color: red
}

        
        
          
        
      

Как пишется

Секция статьи "Как пишется"

Селекторы разделяются знаком >.

Как это понять

Секция статьи "Как это понять"

Последовательность селекторов отражает непосредственную вложенность — селектор справа от оператора должен быть прямым потомком селектора из левой части:

        
          
          article > h3 {  color: red;}
          article > h3 {
  color: red;
}

        
        
          
        
      

К h3.article__heading стили для article > h3 не применятся, т. к. прямой потомок <article>div.article__header, а не <h3>:

        
          
          <article class="article">  <div class="article__header">    <h3 class="article__heading">Заголовок</h3>  </div></article>
          <article class="article">
  <div class="article__header">
    <h3 class="article__heading">Заголовок</h3>
  </div>
</article>

        
        
          
        
      

В этом примере стили к заголовку применятся, потому что <h3> является прямым потомком <article>:

        
          
          <article class="article">  <h3 class="article__heading">Заголовок</h3></article>
          <article class="article">
  <h3 class="article__heading">Заголовок</h3>
</article>

        
        
          
        
      

И тут тоже всё в порядке — <h3> по-прежнему является прямым потомком <article>, потому что располагается на ближайшем уровне вложенности, хоть и следует после div.article__header:

        
          
          <article class="article">  <div class="article__header">…</div>  <h3 class="article__heading">Заголовок</h3></article>
          <article class="article">
  <div class="article__header"></div>
  <h3 class="article__heading">Заголовок</h3>
</article>

        
        
          
        
      

Подсказки

Секция статьи "Подсказки"

💡 Такая комбинация удобна, чтобы выбрать элемент, основываясь на его точном расположении в структуре документа.

Смежные: .element1 + .element2

Секция статьи "Смежные: .element1 + .element2"

Пример

Секция статьи "Пример"
        
          
          label + input {  color: red;}
          label + input {
  color: red;
}

        
        
          
        
      

Как пишется

Секция статьи "Как пишется"

Селекторы объединяются знаком +.

Как это понять

Секция статьи "Как это понять"

Элемент справа от + должен следовать в HTML сразу за элементом слева от +. Проще говоря, правый элемент должен быть соседом левого элемента, чтобы смежный селектор сработал.

Код из примера применится только к такому <input>, который стоит сразу после <label>:

        
          
          label + input {  color: red;}
          label + input {
  color: red;
}

        
        
          
        
      

К этому не применится, т. к. перед <input> идёт <p>:

        
          
          <label></label><p>…</p><input>
          <label></label>
<p></p>
<input>

        
        
          
        
      

При такой разметке стиль применится только к первому <input>, но не ко второму:

        
          
          <label>Лейбл</label><input><input>
          <label>Лейбл</label>
<input>
<input>

        
        
          
        
      

И тут правило не сработает. <label> и <input> — на разных уровнях вложенности:

        
          
          <label>Лейбл</label><div>  <input></div>
          <label>Лейбл</label>
<div>
  <input>
</div>

        
        
          
        
      

Последующие: .element1 ~ .element2

Секция статьи "Последующие: .element1 ~ .element2"

Пример

Секция статьи "Пример"
        
          
          .star:hover ~ .star {  color: red;}
          .star:hover ~ .star {
  color: red;
}

        
        
          
        
      

Как пишется

Секция статьи "Как пишется"

Селекторы объединяются с помощью символа ~ (тильда).

Как это понять

Секция статьи "Как это понять"

Правило применится ко всем блокам, подходящим под правый селектор, при учёте, что они являются соседями блоков из селектора слева от ~. При этом оба селектора должны иметь одного родителя и находиться на одном уровне вложенности. В HTML правый селектор должен идти после левого селектора.

На практике

Секция статьи "На практике"

Realetive

Секция статьи "Realetive"

🛠 Лучше записывать селекторы по одному на строчку — так их легче читать и редактировать:

        
          
          .selector1,code,#id,[attr="value"] {  color: red;}
          .selector1,
code,
#id,
[attr="value"] {
  color: red;
}

        
        
          
        
      

🛠 Объединение увеличивает специфичность правила, поэтому это может быть удобно для переопределения свойств без !important:

Код ниже нельзя редактировать по каким-то причинам:

        
          
          .class1 {  color: red;}
          .class1 {
  color: red;
}

        
        
          
        
      

Увеличим специфичность, чтобы переопределить правило, описанное в нередактируемой части и потому имеющее больший вес:

        
          
          .class1.class2 {  color: green;}.class1 {  color: red;}
          .class1.class2 {
  color: green;
}

.class1 {
  color: red;
}

        
        
          
        
      

В итоге текст в блоке, имеющем сразу и класс .class1 и класс .class2, будет зелёного цвета.

🛠 Получается, что даже невинный пробел уже имеет значение при выборе селектора на любом уровне вложенности.

Независимо от уровня вложенности селектор article h3 «найдёт» <h3> с текстом «Очень вложенный заголовок» и любые другие <h3>, которые располагаются внутри <article>:

        
          
          <article>  <div>    <div>      <div>        <div>          <div>            <div>              <div>                <div>                  <div>                    <h3>Очень вложенный заголовок</h3>                  </div>                </div>              </div>              <h3>Заголовок</h3>            </div>          </div>        </div>      </div>    </div>  </div></article>
          <article>
  <div>
    <div>
      <div>
        <div>
          <div>
            <div>
              <div>
                <div>
                  <div>
                    <h3>Очень вложенный заголовок</h3>
                  </div>
                </div>
              </div>
              <h3>Заголовок</h3>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</article>

        
        
          
        
      

Роман Баранников

Секция статьи "Роман Баранников"

🛠 С помощью смежного комбинатора удобно выбирать группу одинаковых элементов по принципу «все, кроме первого» — например, чтобы задать отступ.

К первому <li> стили не применятся, поскольку перед ним нет другого <li>:

        
          
          <ul>  <li>Первый пункт</li>  <li>Второй пункт</li>  <li>Третий пункт</li>  <li>Четвёртый пункт</li></ul>
          <ul>
  <li>Первый пункт</li>
  <li>Второй пункт</li>
  <li>Третий пункт</li>
  <li>Четвёртый пункт</li>
</ul>

        
        
          
        
      
        
          
          li + li {  margin-top: 1em;}
          li + li {
  margin-top: 1em;
}

        
        
          
        
      

Классический пример — вёрстка «звёздного» рейтинга. Для начала опишем структуру:

        
          
          <div class="rating">  <button>★</button>  <button>★</button>  <button>★</button>  <button>★</button>  <button>★</button></div>
          <div class="rating">
  <button></button>
  <button></button>
  <button></button>
  <button></button>
  <button></button>
</div>

        
        
          
        
      

И стили:

        
          
          button {  border: none;  background-color: transparent;  font-size: 5em;}button:hover,button:focus,button:hover ~ button,button:focus ~ button {  color: #F498AD;}
          button {
  border: none;
  background-color: transparent;
  font-size: 5em;
}

button:hover,
button:focus,
button:hover ~ button,
button:focus ~ button {
  color: #F498AD;
}

        
        
          
        
      

Но сейчас при наведении курсора будут выделяться все элементы после (то есть справа).

Открыть демо в новой вкладке

Чтобы это исправить, мы изменим порядок следования элементов с помощью CSS-свойства direction: rtl.

Добавим это свойство родителю звёздочек .rating:

        
          
          .rating {  direction: rtl;}button {  border: none;  background-color: transparent;  font-size: 5em;}button:hover,button:focus,button:hover ~ button,button:focus ~ button {  color: #F498AD;}
          .rating {
  direction: rtl;
}

button {
  border: none;
  background-color: transparent;
  font-size: 5em;
}

button:hover,
button:focus,
button:hover ~ button,
button:focus ~ button {
  color: #F498AD;
}

        
        
          
        
      
Открыть демо в новой вкладке