Не все то золото, что есть в SASS/LESS/STYLUS

Nikolay Pachkov
3 min readJul 16, 2017

--

Хочу предупредить — описаная мной проблема вынесена из многолетнего личного опыта. Я всего лишь попробую дать опору сомневающимся и посеять зерно сомнения для убежденных.

Основано на реальных событиях:
https://medium.com/@jakobud/how-to-do-sass-grandparent-selectors-b8666dcaf961

Если вы используете препроцессоры для CSS такие как SASS/SCSS/LESS/STYLUS то возможно пишете селектор как-то так (для примера выбран SCSS):

$context: 'app';.#{$context}-element {
...
}

Или соблюдая БЭМ, так:

.block {
&__element {
...
}
}

Да даже так:

.block {
$context: &;
display: flex;
&__element {
color: $base-color;
#{$сontext}:hover & {
color: $hover-color;
}
}
}

А если используете Stylus, то можно это (пример из документации):

.foo
&__bar
&_baz
width: 10px

^[-1]:hover &
width: 20px

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

Это про вас? Вынужден сообщить, что вы в группе риска.

Дело в том, что разбивая подобным образом селектор, вы разрываете его целостность. Это значит что вы не сможете использовать поиск/замену/автокомплит и переход к объявлению селектора из HTML/JS или наоборот. Что более важно, это вносит дополнительную сложность.

Так это не проблема? Вы скажете:

Я не использую ни поиск, ни рефакторинг в SCSS. Поиск не нужен так как я знаю что и где лежит, а так как я знаю где и что лежит мне не составляет труда переименовывать селектор сперва в SCSS а затем в HTML/JS. Нужно лишь немного подумать.

Если вы полностью следуете БЭМ или у вас что-то похожее (однофайловые компоненты Vue), то это сильная аргументация. Но возможно вам следует попробовать использовать возможности вашего кодового редактора в поиске и замене — это увеличивает производительность, позволяя автоматизировать процесс.

Если у вас есть код на SCSS, который не разделен на мелкие компоненты, например описывает стили какой-нибудь страницы, а верстка находится где-то далеко в шаблонах PHP/Twig/etc, и вы пользуетесь подобной конкатенацией — то не обманывайте себя, в таком случае поиск и переименование не так просты. А если что-то упустить?

Но главная проблема в том, что это неоправданно усложняет код.

Давайте еще раз взглянем на этот пример:

.block {
$context: &;
display: flex;
&__element {
color: $base-color;
#{$сontext}:hover & {
color: $hover-color;
}
}
}

Где мы подразумевали:

.block {
display: flex;
}
.block .block__element {
color: $base-color;
}
.block .block__element:hover {
color: $hover-color;
}

В чем разница?

В первом варианте мы используем больше средств языка чем во втором варианте. Сохранение контекста в переменную, конкатенация и амперсанд.
Во втором варианте дублируется название блока, он стал ближе к CSS.

Вот именно! Второй пример стал похож на CSS. Если наша итоговая цель — написать CSS, то зачем мы отдаляемся от него, когда можем этого избежать?

Я знаю, согласится будет не просто, но первый вариант СЛОЖНЕЕ. Его сложнее понять, а использование сохранения контекста в переменной, для получения его потом в потомках, делает эту задачу временами невыносимой.
Это попросту добавляет еще один барьер, на пути к пониманию кода как для автора так и для стороннего наблюдателя.
И это очень важно. Простой код лучше сложного.

Так какие там преимущества были?
Имя блока не повторяется? Подождите, так ли это ужасно?
Его приходится постоянно копировать. Это та небольшая плата за снижение сложности. Но в итоге вы получаете простой для чтения SCSS, где нет манипуляций с контекстом/неймспейсом.

Обратите внимание — это никаким образом не противоречит БЭМ.

Серьезно, где в документации БЭМ сказано что требуется конкатенация для получения селектора? Зачем вновь изобретать вложенность, пусть только на этапе SCSS если одна из задач решаемая с помощью БЭМ это минимизация количества вложенных селекторов?

Подождите, мне нужно признаться.

Первым моим препроцессором был LESS и когда они реализовали возможность конкатенации c помощью амперсанда, я тут же начал это использовать. Казалось логичным что так и нужно писать в БЭМ стиле, получая селектор элемента через обращение “&__”. Потом где-то, я наткнулся на мнение что так делать нет нужды. На тот момент мне показалось что человек просто не понимает, делать так было необходимо. Мне вот только мешало что из-за разрыва в селекторе IDE не помогает с рефакторингом, в то время как проект стремительно рос. Я стал подумывать написать о плагине к IDE, который исправит эту проблему. Но прошло пару лет и постепенно, боясь сперва себе признаться, я понял что он был прав.

--

--