Кешируем селекторы здесь и сейчас
Будни верстальщика
Когда разрабатываешь наборы своих компонентов, очень часто задумываешься: а что делать когда у тебя кнопка может быть частью, например, группы кнопок или тулбара и менять при этом свой вид?
Конечно же приверженцы БЭМ скажут: модификатор ставь. И закроют вопрос.
.button {}
.button--menu {}
.button--dropdown {}
.button--label {}
Эээ, погодите… не всем нравится БЭМ, не все хотят лишние классы к элементам добавлять, давайте просто применим контекстный селектор!
.menu .button {}
.dropdown .button {}
.label .button {}
В общем, предстоит вам распихать каскадов по всем файлам родительских компонентов. Ну или как минимум положить это всё в самый низ файла стилей самой кнопки, чтобы не искать потом где определили.
Самое время вспомнить о родительском селекторе в SCSS: &. Следующая конструкция развернётся именно в то, что нам нужно:
.button {
.menu & {}
.dropdown & {}
.label & {}
}
А знаете, что мы можем сделать на CSS-in-JS решениях вроде Styled Components, Emotion и идентичных? Мы можем обратиться прямо к компоненту-родителю из компонента-ребёнка! Ровно таким же образом, как в SCSS, но без обращения к классам (они всё равно будут сгенерированы). И не то чтоб я прямо топил за такой подход, но иногда это довольно таки удобно:
import {Menu} from ‘../Menu’;
import {Dropdown} from ‘../Dropdown’;
const Button = styled.button`
border: 1px solid darkgreen;
background: darkkhaki;
${Menu} & {
border: none;
background: transparent;
}
${Dropdown} & {
text-indent: -9999px;
&::after {
// create some arrow maybe
}
}`;
В чём тут выгода? Очевидно, теперь компонент кнопки хранит все свои возможные состояния, вам не нужно запоминать, где и во что кнопка может превратиться.
Кнопка плохой пример? Окей, есть иконки. С иконками подобное представить будет легче: иконка в кнопке, в ссылке, в лейбле, в поле ввода, в меню…
В SCSS есть ещё один интересный трюк: кеширование родительского селектора. Правда, область видимости останется той же и финта ушами с объединением состояний компонента не выйдет, но это всё равно весьма мощная вещь:
.menu {
display: flex;
padding: 0;
list-style: none;
$this: &; // кешируем
&__item {
margin: 0 4px 0 0;
}
&__link {
display: block;
padding: 4px 8px;
text-decoration: none;
&:hover,
#{$this}__item--active & { // используем
background-color: $gray-very-light;
}
}
}
Здесь мы взяли родительский селектор и использовали его для изменения цвета наведённой ссылки активного пункта меню. Превратится эта вся конструкция в следующее:
...
.menu__item--active .menu__link {
...
Как видим, хоть до внедрения родительских и обратных селекторов в CSS ещё далеко, но это не значит, что мы не можем себе немного облегчить зрительную нагрузку уже сейчас.