38 Модуль 8 Архитектура стилей 16 мин урок 13 из 25

Sass: что реально нужно, а что вредно

Половина возможностей препроцессора переехала в обычный CSS. Разбираем, что осталось незаменимым, а что теперь только вредит.

Что ты научишься делать

  • Поймёшь принципиальную разницу между переменными Sass и CSS
  • Увидишь, во что превращается вложенность и сколько кода даёт миксин
  • Решишь для конкретного проекта, нужен ли препроцессор вообще

#Зачем он был нужен

Sass появился, когда в CSS не было ни переменных, ни вложенности, ни функций. Он давал всё это ценой одного шага сборки — и это был честный обмен.

С тех пор CSS сильно вырос. Переменные есть с 2016 года, вложенность — с 2023, математика через calc() была всегда. Половина причин брать препроцессор исчезла.

Вопрос перестал быть «использовать ли Sass». Он стал «что именно из Sass мне ещё нужно».

Интерактивный разбор доступен при включённом JavaScript.

#Переменные: разница принципиальная

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

Переменная Sass существует только во время сборки. В готовом файле её нет — там подставлено значение. Поменять её из браузера, из скрипта или медиазапросом невозможно.

Переменная CSS живёт в браузере. Наследуется, переопределяется в любом селекторе, меняется скриптом и читается через getComputedStyle.

Sass: <code>$accent</code>CSS: <code>--accent</code>
Когда существуетТолько при сборкеВ браузере, во время работы
Наследуется потомкамНетДа
Меняется в медиазапросеНетДа
Меняется скриптомНетДа
ТемизацияТолько пересборкойПереключением атрибута
Где уместнаЗначения, известные заранее: брейкпоинты, шаги шкалыВсё, что может меняться: цвета, размеры, темы

#Вложенность: удобно и опасно

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

Каждый уровень добавляет часть к селектору. Три уровня — и получается вес, который потом нечем перебить, кроме ещё более длинного селектора.

Так не надо

.page {
  .sidebar {
    .card {
      .title { font-size: 18px; }
    }
  }
}

/* На выходе: .page .sidebar .card .title — вес 0-4-0 */

Читается приятно, а результат почти неперебиваемый. Чтобы поменять размер в одном месте, придётся написать селектор ещё длиннее.

Так надо

.card {
  padding: 16px;

  &__title { font-size: 18px; }
  &:hover { box-shadow: var(--shadow-2); }
}

/* На выходе: .card__title — вес 0-1-0 */

Вложенность используется для группировки, но селектор остаётся плоским. Амперсанд склеивает имя, а не добавляет уровень.

#Миксины: копирование, а не переиспользование

Миксин выглядит как функция, но ведёт себя как шаблон: при каждом вызове его содержимое вставляется целиком.

Десять вызовов миксина из восьми свойств — это восемьдесят строк в готовом файле. На глаз этого не видно: исходник-то короткий.

CSSЧто лучше вынести в класс
/* Плохо: миксин копирует одно и то же в каждый вызов */@mixin card-base {  padding: 16px;  background: #fff;  border-radius: 14px;  box-shadow: 0 2px 8px rgb(20 24 48 / .08);}.product { @include card-base; }.article { @include card-base; }.promo   { @include card-base; }/* Лучше: общий класс в разметке, ноль дублей в CSS */.card {  padding: 16px;  background: #fff;  border-radius: 14px;  box-shadow: 0 2px 8px rgb(20 24 48 / .08);}

Миксин оправдан там, где повторяется логика, а не набор свойств: сложный медиазапрос, обёртка над градиентом с параметрами, генерация нескольких правил разом.

#Что осталось незаменимым

  • Циклы и списки. Сгенерировать двадцать классов отступов по шкале в чистом CSS нечем. Это главная причина, по которой Sass до сих пор в проектах.
  • Разбиение на файлы через @use. В CSS есть @import, но он делает лишний сетевой запрос и работает медленнее. Sass склеивает файлы при сборке.
  • Функции с вычислениями. Округление, работа со списками, генерация имён — в CSS этого нет.
  • Общий код для нескольких проектов. Библиотека миксинов, подключаемая в несколько сайтов сразу.
CSSРади этого и берут Sass
        $spaces: (0: 0, 1: 4px, 2: 8px, 3: 12px, 4: 16px, 6: 24px, 8: 32px);        @each $name, $value in $spaces {          .p-#{$name} { padding: $value; }          .m-#{$name} { margin: $value; }          .gap-#{$name} { gap: $value; }        }        /* Двадцать одно правило из семи строк исходника.           В чистом CSS их пришлось бы написать руками */

#@use вместо @import

Старый @import в Sass объявлен устаревшим. Он подключал файлы в общее пространство имён: две переменные с одинаковым именем из разных файлов молча перетирали друг друга.

@use подключает файл под своим именем — становится видно, откуда что взялось.

CSSСовременная организация
        /* main.scss */        @use "tokens";        @use "mixins" as m;        .card {          padding: tokens.$space-4;          @include m.card-shadow;        }        /* Видно, что переменная из tokens, а миксин из mixins.           При старом @import это было бы неотличимо */

#Когда НЕ надо

  • Ради вложенности. Она есть в чистом CSS и работает так же. Это больше не аргумент.
  • Ради переменных. Переменные CSS мощнее: они живут в браузере. Sass-переменные — шаг назад для всего, что связано с темами.
  • На маленьком проекте. Сборка добавляет шаг между правкой и результатом. На лендинге в пятьсот строк это чистая потеря времени.
  • Когда команда не знает Sass. Обычный CSS читают все. Препроцессор — это ещё один язык, который придётся объяснять каждому новому человеку.

#Как решать в конкретном проекте

  1. Есть ли уже сборка?

    Если проект и так собирается — Sass почти бесплатен. Если сборки нет, он тянет за собой всю инфраструктуру ради нескольких удобств.

  2. Нужны ли генерируемые классы?

    Набор утилит, шкала отступов, сетка колонок — здесь циклы окупаются сразу.

  3. Сколько тем?

    Больше одной — цвета обязаны быть на переменных CSS независимо от того, есть Sass или нет.

  4. Кто будет это поддерживать?

    Если проект передадут человеку без опыта сборки, чистый CSS окажется дешевле в поддержке, даже если писать его дольше.

Где спотыкаются почти все

Тема собрана на переменных Sass

Почему В готовом CSS переменных нет — переключать нечего. Тёмную тему приходится делать вторым файлом.

Как надо Всё, что зависит от темы, — только на переменных CSS. Sass оставь для того, что известно на этапе сборки.

Вложенность повторяет структуру разметки

Почему Селекторы вырастают до четырёх уровней, специфичность становится неперебиваемой, а перенос блока в другое место ломает стили.

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

Миксин вместо общего класса

Почему Каждый вызов копирует все свойства. Исходник короткий, готовый файл раздувается.

Как надо Повторяется набор свойств — заводи класс. Миксин нужен для повторяющейся логики.

Используется устаревший @import

Почему Общее пространство имён: переменные из разных файлов молча перетирают друг друга.

Как надо Переходи на @use — источник каждой переменной становится виден.

Препроцессор preprocessor
Инструмент, превращающий расширенный синтаксис в обычный CSS на этапе сборки.
Переменная Sass Sass variable
Значение, подставляемое при сборке. В готовом файле её нет.
Миксин mixin
Шаблон правил, содержимое которого копируется в каждое место вызова.
Интерполяция interpolation
Подстановка значения в имя селектора: .gap-#{$name}.

Проверь себя

  1. Почему тему нельзя собрать на переменных Sass?

    Sass-переменная подставляется при сборке. В браузере остаётся только конечное значение.

  2. Во что превратится вложенность <code>.page { .card { .title { … } } }</code>?

    Каждый уровень добавляет часть к селектору. Отсюда и незаметный рост специфичности.

  3. Десять вызовов миксина из восьми свойств дадут в готовом CSS…

    Миксин — это шаблон, а не ссылка. Для повторяющегося набора свойств дешевле общий класс.

  4. Что из Sass до сих пор нечем заменить в чистом CSS?

    Вложенность и переменные в CSS уже есть. А сгенерировать двадцать классов по списку — нечем.

  5. Чем <code>@use</code> лучше <code>@import</code> в Sass?

    Старый <code>@import</code> сваливал всё в общее пространство имён, и переменные молча перетирали друг друга.

Задание

Разобрать повторы

Перед тобой чистый CSS с тремя одинаковыми наборами свойств и цветами, размазанными по правилам. Sass тут нет и не будет — задача в том, чтобы решить ту же проблему средствами самого CSS.

Вынеси повторяющийся набор в общий класс .card, а цвета — в переменные :root. Разметку можно менять: добавь общий класс к трём блокам.

Открыть в песочнице
    Подсказка 1

    Добавь класс в разметку: <article class="card product">, <article class="card promo"> и так далее.

    Подсказка 2

    Общее вынеси в .card, а в .promo и .note оставь только то, чем они отличаются.

    Подсказка 3

    Цвета — в :root { --color-surface: #fff; --color-accent: #6544e0; --color-muted: #5b6070; }

    Показать решение
    HTMLindex.html
    <article class="card product">  <h3>Раф</h3>  <p>240 ₽</p></article><article class="card promo">  <h3>Акция</h3>  <p>Второй кофе бесплатно</p></article><article class="card note">  <h3>Заметка</h3>  <p>Работаем до 22:00</p></article>
    CSSstyle.css
    :root {  --color-surface: #ffffff;  --color-accent: #6544e0;  --color-muted: #5b6070;  --radius-md: 14px;  --space-4: 16px;}/* Общее — один раз */.card {  padding: var(--space-4);  background: var(--color-surface);  border-radius: var(--radius-md);  box-shadow: 0 2px 8px rgb(20 24 48 / .08);  margin-bottom: 12px;}/* Отличия — только они */.promo { border-left: 3px solid var(--color-accent); }.note { color: var(--color-muted); }h3 { margin: 0 0 6px; font-size: 16px; }p { margin: 0; font-size: 14px; }

    Проверь себя