Понять комбинаторные селекторы и селекторы потомков в CSS

от автора

Периодически я сталкиваюсь с проблемой — не хочу ставить лишний класс элементу внутри различных кнопок, ссылок и label-ов. Зачастую это текст, который нужно подсветить или галочка чекбокса или маленькая иконка.

Как же справиться с такой проблемой? Тут самым простым и понятным решением будет наследование. Возьмём код ссылки с иконкой, которую нужно анимировать:

<a href="#" class="text_arrow-btn">   <span>Все товары</span>   <svg width="37" height="15" viewBox="0 0 37 15" fill="none" xmlns="http://www.w3.org/2000/svg">     <path d="M0 7.5H36M36 7.5L31.1538 0.5M36 7.5L31.1538 14.5" stroke="#323F4C"></path>   </svg> </a>

Сделать это несложно, достаточно просто прописать несколько правил:

/*БАЗОВЫЕ ПРАВИЛА*/ a {   text-decoration: none;   color: inherit;   font-family: sans-serif; }  .text_arrow-btn {   display: flex;   align-items: center;   font-size: 22px;   line-height: 142%; }  /*ИСПОЛЬЗОВАНИЕ НАСЛЕДОВАНИЯ*/ .text_arrow-btn span { /*Для span которые внутри ссылки*/   margin-right: 16px; }  .text_arrow-btn svg { /*Для svg которые внутри ссылки*/   transition: transform 0.3s;   width: 36px;   height: 14px; }  .text_arrow-btn:hover span {   text-decoration: underline; }  .text_arrow-btn:hover svg {   transform: translateX(12px); }

Пробел обращается ко всем детям элемента с подходящим селектором. Символ «больше» > обратится только к прямому потомку.

Да, в CSS выглядет не очень, но в SASS всё уже немного приятнее:

a    text-decoration: none   color: inherit   font-family: sans-serif   color: #323F4C   .text_arrow-btn    display: flex    align-items: center    span       margin-right: 16px    svg       transition: transform 0.3s       width: 36px       height: 14px    path       transition: stroke 0.3s    &:hover       svg          transform: translateX(12px)       span          text-decoration: underline    &:active       color: #B6B5B5       path          stroke: #B6B5B5

Думаю что этим я глаза никому не открыл — вполне стандартная история.

Соседний комбинатор — «+»

Однако, на этом мы не останавливаемся. Теперь другая задача — стилизация чекбокса. Если вы хоть раз сталкивались с этой проблемой, то вы знаете лицо боли. Потому что убрать стандартные стили просто так не получится, получится только убрать чекбокс к чёртовой бабушке и стилизовать заново из div или span. Но чтобы добавить неинтерактивным элементам интерактивности придётся использовать JS. Или не придётся?..

Тут нам поможет волшебный + — это комбинатор родственных элементов. Он объединяет два элемента, находящихся на одном уровне, и второй должен следовать СРАЗУ за первым.

Звучит сложно — работает просто. Выбирается следующий сразу за элементом селектор. Вот так:

<label class="main-checkbox">   <input type="checkbox">   <span>     <svg width="13" height="10" viewBox="0 0 13 10" fill="none" xmlns="http://www.w3.org/2000/svg">       <path d="M1 3.85714L5.30435 9L12 1" stroke="#323F4C"></path>     </svg>   </span> </label>
.main-checkbox    cursor: pointer    span       display: inline-block       width: 24px       height: 24px       background: #F8F8F8       display: flex       align-items: center       justify-content: center       transition: background 0.3s       svg          width: 12px          height: 9px          opacity: 0          transition: opacity 0.3s    &:hover       span          background: #EBEBEB    input       display: none       &:checked+span /*вот он*/          background: #F8F8F8          svg             opacity: 1

Обращаем внимание на: &:checked+span тут «+» говорит нам о том, что будет выбран следующий за чекнутым input span. И вуаля — чекбокс работает как часы и он стилизован.

Родственный комбинатор — «~»

Но мы не останавливаемся. Имеем ещё одну задачу: чекбокс у которого внутри идёт span и svg одновременно и нужно при наведении изменить цвет и текста и svg. Да, можно обернуть элементы в div и использовать +, но фу, лишний тег — это полный отстой.

Тут нам поможет тильда ~ (не путать с тильтом). Этот символ не выражает усталость и безысходность — совсем наоборот. Он даёт нам выбрать теги, находящиеся на одном уровне с элементом.

Вот наш чекбокс с иконкой:

 <label class="radio-sort">    <input type="checkbox">    <span>По возрастанию цены</span>    <svg width="11" height="14" viewBox="0 0 11 14" fill="none" xmlns="http://www.w3.org/2000/svg">      <path d="M5.5 14V1M5.5 1L10 5.78947M5.5 1L1 5.78947" stroke="#323F4C" />    </svg> </label>

И вот стили:

.radio-sort    font-family: sans-serif    margin-right: 48px    cursor: pointer    display: flex    align-items: center    &:last-child       margin-right: 0    input       display: none    span       display: inline-block    svg       width: 10px       height: 14px       display: inline-block       margin-left: 12px    input:checked + span       font-weight: 800    input:hover + span       color: #1eaf9f    input:hover ~ svg       path          stroke: #1eaf9f

тильда выберет следующий за span svg — очень удобно!

Итак, подведём итог.

Пробел — выберет все дочерние элементы, соответствующие селектору:

Знак больше > выберет только дочерние элементы, являющиеся прямыми потомками:

Знак + выберет следующего за элементом потомка:

Тильда ~ выберет всех одноуровневых потомков:

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
Использовали ли вы раньше + или ~?
50% Да 3
33.33% Нет, но буду 2
16.67% Нет, мне это не нужно 1
Проголосовали 6 пользователей. Воздержавшихся нет.

ссылка на оригинал статьи https://habr.com/ru/post/722962/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *