Привет, Хабр! На связи Герман, TL Frontend-разработчик в Webest, и сегодня хочу поделиться тем, почему мы продолжаем использовать препроцессор SASS/SCSS в наших проектах, несмотря на растущую популярность Tailwind и CSS-in-JS решений.
К слову, мы не «олдскульные фанаты» SASS, и Tailwind тоже используем, но в зависимости от типа проекта. Комбинированный подход дает гибкость, особенно в масштабируемых фронтенд-системах.
Что такое SASS/SCSS
SASS — это препроцессор CSS, который позволяет использовать переменные, функции, условия, циклы и другие конструкции, отсутствующие в стандартном CSS.
SASS имеет два синтаксиса:
-
SASS — оригинальный синтаксис с отступами вместо фигурных скобок.

SAAS -
SCSS — более современный и популярный вариант, максимально похожий на CSS (добавляет расширения без изменения привычной структуры).

SCSS
Мы в своей практике используем исключительно SCSS — он проще для вхождения и легко интегрируется с современными фреймворками и сборщиками.
Зачем используем в 2025
SASS появился в 2007 году и сразу стал прорывом: позволял использовать переменные, вложенность и миксины еще до того, как что-то похожее появилось в стандарте CSS. В 2010-е он стал де-факто стандартом в крупных проектах.
Позже появились альтернативы: LESS, Stylus, еще позже — CSS-in-JS и Tailwind. Многие стали отказываться от SASS, когда в нативном CSS появились переменные, @custom-media, clamp(), вложенность и другие возможности. Поэтому сейчас SASS воспринимается не как «обязательный инструмент», а как осознанный выбор для архитектуры и масштабируемости.
Мы используем комбинированный подход, в зависимости от проекта. Где-то используем SASS в «классическом виде»: написал стили – скомпилировал – готово. Где-то он используется в связке с CSS Modules, в частности в крупных проектах на Vue/Nuxt.
Например, в разработке интернет-магазина для проекта X с тысячами карточек товаров Tailwind оказался удобен на старте, но при масштабировании код стал тяжело поддерживать. Вернувшись к SCSS-модулям, мы сократили дублирование кода и сделали поддержку проще.
Несмотря на то, что в CSS появляется все больше нативных возможностей (например, CSS variables, container queries, nesting и т.д.), SASS все еще дает разработчикам:
Быструю разработку с DRY-принципами.
Чистую архитектуру за счет деления на модули.
Возможность писать более выразительный и масштабируемый код.
Преимущества для масштабирования
Начнем с возможностей, которых пока нет в CSS.
Миксины
Миксин – это конструкция которая может содержать определенный набор свойств, @extend, вызовов функций и циклов. Все, что будет объявлено внутри миксина можно переиспользовать, указав название миксина с ключевым словом @include.
Простой пример, миксин для добавления анимации css-свойствам:
// Создаем сам миксин который будет добавлять анимацию для css-свойств
@mixin transition(
$property: all,
$duration: .3,
$function: ease,
$delay: null
) {
transition-duration: $duration;
transition-property: $property;
transition-timing-function: $function;
@if $delay {
transition-delay: $delay;
}
}
// Применяем миксин к селектору
.some-selector {
@include transition((color, background-color));
}
С таким кодом нет необходимости создавать для каждого блока transition-свойство, просто используем миксин, передаем нужные свойства для анимации и готово!

Миксины здорово экономят время. Мы сами в этом убедились, когда в e-commerce проекте нужно было единообразно управлять анимацией карточек. Вместо копипаста transition-свойств по всему коду вынесли в миксин и смогли централизованно обновлять поведение.
Условия (@if, @else)
SASS позволяет использовать условные конструкции. Например, в примере о миксинах был следующий блок с задержкой анимации.
@if $delay {
transition-delay: $delay;
}
В нем мы можем указать нужное свойство или несколько свойств. Например, миксин который добавляет внешние и внутренние отступы элементу, если переменная $needOffset содержит истинное значение:
@if ($needOffset) {
margin-block: 10px;
margin-inline: 20px;
padding: 8px;
}
В данном случае если четвертым аргументом передаем не null-значение, то для анимации появится задержка. Конечно, значение должно быть валидным, например, 0.3s, 500ms.
Дебаггинг для поиска проблемной вёрстки
Иногда на проекте появляется проблема: «вёрстка поехала» или неожиданно появился горизонтальный скролл, хотя все элементы находится в контейнере. Проверили разметку, все элементы на месте, а верстка все равно едет. В таких случаях помогает быстрый отладочный прием — включить режим дебага через SCSS-переменную:
$debug: true;
@if ($debug) {
* {
outline: 1px solid red;
}
}
Важно, что здесь используется свойство outline, а не border — оно не влияет на размеры элементов (помним о box-sizing) и не смещает layout. Такой приём позволяет очень быстро находить проблемные участки верстки и экономит время на дебаг.
Переменные
SASS-переменные – одна из базовых возможностей препроцессора. Но с приходом CSS-переменных мы почти полностью перешли на них. Именно от переменных SASS в пользу CSS Variables, так как последние работают в runtime, с таким работать удобнее и могут быть случаи когда с переменными приходится работать через JS.
Однако, если значение не должно изменяться в runtime, старые добрые SASS-переменные остаются удобными.
Мы используем оба подхода. для темизации интерфейса удобнее CSS Variables, ведь ими легко управлять через JS прямо в runtime. Но там, где значения не должны меняться (брейкпоинты, базовые размеры), оставляем SCSS-переменные.

Импорты
SASS обрабатывает импорты на этапе компиляции, в отличие от @import в CSS, который создаёт дополнительные HTTP-запросы. Для больших проектов это критично: мы можем разбивать код на модули, но при этом не перегружаем сеть.
В SCSS импорты срабатывают ещё на стадии сборки, поэтому на выходе всегда один CSS-файл (или несколько, если так задумано архитектурой). Это удобно: код структурирован, итог лёгкий.
Импорты в SCSS не раз спасали архитектуру в больших проектах. Например, в корпоративной системе с десятками страниц мы разделили стили на отдельные модули — хедер, футер, карточки, таблицы. А на продакшн все собиралось в один оптимизированный файл без лишних запросов.
Адаптивы
Чаще всего в адаптиве нужно плавно изменять свойства. Например, размер шрифта или отступы в зависимости от ширины экрана. Вместо множества медиа запросов удобно использовать CSS-функцию clamp(). Она создает не фиксированное значение, а «резиновое», которое растет или сжимается в зависимости от ширины экрана. Мы внедряем ее во всех проектах с адаптивом, например, для типографики и отступов.
В SCSS это можно автоматизировать с помощью функции:
@function fluid($min, $max, $min-vw: 360, $max-vw: 1440) {
$slope: math.div(($max - $min), ($max-vw - $min-vw));
$y-intercept: $min - $slope * $min-vw;
@if $min > $max {
@return clamp(
#{$max}px,
#{$y-intercept}px + #{$slope * 100}vw,
#{$min}px
);
}
@return clamp(
#{$min}px,
#{$y-intercept}px + #{$slope * 100}vw,
#{$max}px
);
}
Функция fluid принимает четыре аргумента:
$min — минимальное значение свойства (например, 16 для шрифта в 16px).
$max — максимальное значение свойства (например, 24 для шрифта в 24px).
$min-vw — минимальная ширина экрана, при которой применяется $min (по умолчанию 360px).
$max-vw — максимальная ширина экрана, при которой применяется $max (по умолчанию 1440px).
То есть мы задаем «коридор» значений, где между ними изображение плавно изменяется. И на выходе получаем clamp-функцию с автоматически рассчитанными параметрами.
Заключение
Да, SASS уже не на хайпе, как раньше. Но он по-прежнему остается мощным инструментом, особенно в проектах с жесткими требованиями к архитектуре, масштабируемости и стабильности.
Мы комбинируем SASS с современными практиками и не видим причин полностью от него отказываться, по крайней мере, пока нативный CSS не догонит его по возможностям.
А вы используете SASS или другие препроцессоры в современной разработке или решили отказаться в пользу других инструментов?
Ares_ekb
Это моё личное и наверняка ошибочное мнение, но я думаю что CSS‑in‑JS уже устарел. Это какой‑то ад с точки зрения отладки и производительности. Плюс это лишний слой абстракции. Просто нормально организованный CSS — это такой кайф после CSS‑in‑JS
Насчёт Tailwind, это вкусовщина, но я тоже не фанат. Для меня это выглядит примерно как использование inline‑стилей
Насчёт SASS/SCSS. Я не вижу достаточно количества плюсов, которые перевешивают минусы в виде добавления ещё одного слоя абстракций, усложнения сборки
AlexEp Автор
Спасибо за ваше мнение. А чем в вашем случае SASS/SCSS усложняет процесс сборки?
Ares_ekb
1) У меня в целом достаточно ортодоксальный взгляд на это. Например, есть мнение, что для библиотек вообще не нужна сборка и я с этим согласен. Потому что в конечном приложении, которое эту библиотеку будет использовать, наверняка уже будет какой‑то бандлер. Т.е. я просто пишу TypeScript и CSS код и не заморачиваюсь со сборкой, а для SCSS мне придётся что‑то тянуть в проект.
Или даже если я использую сборщик, всё равно это дополнительное время на каждую сборку. При обновлении версий сборщиков наверняка будет что‑то ломаться. Я хз, транспилировать SCSS отдельно или для vite есть плагин, а если решу отказаться от vite и какой‑нибудь bun возьмет на себя полностью сборку или ещё какой‑то очередной мегасборщик, то мне придётся адаптировать и сборку SCSS? У меня сейчас настроен Stylelint для CSS, а для SCSS мне нужно будет тянуть дополнительный плагин? Потом я обновлю версию Stylint, а для SCSS новой версии плагина не будет. У меня просто болит голова, когда я начинаю думать о сборке проектов в вебе. Поэтому чем оно тупее и проще, тем лучше, а лучше вообще без сборки.
2) Но даже это не основной стопер от использования SCSS. На мой взгляд это просто лишняя абстракция. Если я использую CSS, то в браузере и в исходном коде у меня идентичные стили, мне это проще отлаживать, мне проще поправить стиль в браузере, скопировать его обратно в код, или даже не копировать, а просто прямо в браузере и сохранить в файл если это настроено.
3) CSS в отличие от SCSS — это стандарт. Он более распространен. Зачем мне забивать свой мозг тем как в SCSS например переменные объявляются? И зачем мне заставлять остальных людей на проекте делать это? Изучили CSS и этого достаточно.
4) Если в стилях хочется сделать что‑то сложное, то есть два пути: а) усложнить CSS (используя SCSS или CSS‑in‑JS) или б) переформулировать задачу, чтобы в стилях не требовалось делать ничего на столько сложного. Мне ближе вариант б). Когда‑то давно когда CSS был очень ограниченным, когда были сложности с кросс‑браузерной вёрсткой препроцессоры имели смысл. Сейчас я просто не вижу в них смысла. Я не понимаю какой профит мне даст SCSS, чего я не могу сделать на обычном CSS.
AlexEp Автор
Благодарю за развернутый ответ, есть над чем подумать.
andreysam
А как вы используете ts без сборщика?
Ares_ekb
Использую tsc в библиотеках, хотя в теории это не обязательно. А в самом приложении уже tsc+vite. Всё равно в конечном приложении будет какой-то бандлер.
Если сайт совсем простой типа лендинга, то там и TypeScript не особо нужен.
Наверное я преувеличил уровень сложностей при добавлении в эту схему SCSS, но я столько намучился со сборкой, что мне нужны очень веские причины, чтобы хоть на чуть-чуть её усложнять.
shoorick
При компиляции SCSS по умолчанию создаётся map-файл, ссылка на который попадает в готовый CSS-файл. Браузерный отладчик (как минимум, в Хроме) видит такое и показывает именно исходный SCSS-код.
Ну и вы можете дописывать CSS непосредственно в SCSS-файл, это будет нормально восприниматься компилятором.
Ares_ekb
Согласен, но для меня это дополнительный источник проблем. Схема без дополнительного шага сборки, без map-файлов, без дополнительных языковых конструкций в любом случае проще.
Так конечно можно далеко зайти, например, зачем нужна Java, если всё можно писать на ассемблере. Но SCSS добавляет уж слишком мало на мой взгляд к CSS.
Mind315
кстати, если верить State of CSS 2024
SASS/SCSS все еще максимально используется в 70% случаях +-
AlexEp Автор
Да, видел этот отчёт. Интересно, что при росте популярности Tailwind, SASS/SCSS все еще уверенно держит позиции.
Ares_ekb
Спасибо за ссылку! Я забыл про эту статистику. Меня удивляют эти цифры, я их объясняю для себя только legacy проектами. Странно, что в 2022 году Sass/SCSS использовался 57%, в 2023 - 52%, а в 2024 - 67%. Вряд ли он так начал набирать популярность...
Но вообще, я думаю, что не всегда стоит слушать других. Вполне возможно, что у меня очень специфический взгляд на веб-разработку. Я считаю, что с чистым CSS лучше, но не факт, что такой подход работает на любых проектах
Mind315
ну, почему только легаси? Если посмотреть онлайн школы, крупные и маленькие - в большинстве своём там Sass/SCSS. То есть используют не только динозавры, но и современные разработчики и будущие тоже.
Ares_ekb
Это спекуляция с моей стороны, я не знаю точно почему там учат Sass/SCSS. Я думаю по инерции или потому что он всё ещё много где используется.
Кстати у Kevin Powell есть видео от 2023 года, где он говорит, что ему больше нравится как реализована вложенность стилей в SCSS, чем в CSS, нужны миксины, циклы и условия. В целом как и у автора этой статьи. Лично я вполне могу обойтись без этих вещей. И я даже не уверен, что мне хотелось бы чтобы они появились в CSS, потому что это выглядит дополнительным усложнением. Есть вещи, которые очень нужны: разные селекторы, анкоры, флексбоксы, гриды, разные улучшения связанные с анимацией и т.д. Это реально упрощает разработку, но насчет тех же миксинов я вообще никогда не переживал
alexnozer
Я разделяю ваш взгляд. Для себя тоже отказался от SCSS и предпочитаю минимум или полное отсутствие инструментов сборки. С таким подходом всё просто работает ©
Delagen
В большинстве может быть и нет, но много где хотелось бы один бандл CSS, ну и возможность из кучи файлов собрать единое при обычном CSS тоже та ещё задача.
Мы используем SCSS для контроля кода, во первых мы на базе Figma генерируем набор взаимосвязанных переменных с именованием от дизайн токенов, соответственно потом разработчик не пишет напрямую в коде
var(--name), а использует наш модуль какЧто дает во первых контроль, что никто не будет использовать несуществующие переменные, во вторых никто не ошибется в наименовании переменных сделав таким образом ошибку, в третьих не надо полагаться на автодополнение IDE, которая не совсем может понимать ваш код, а к переменным можно и добавить всякую мета информацию типа SassDOC, что удобно подсвечивает deprecated и в принципе описание переменных
Ares_ekb
Бандл CSS в итоговом приложении будет сгенерен с помощью vite.
Мы не используем на столько активно переменные.
Наверное у нас более примитивная схема. Создаётся React‑компонент, например, ModelExplorer, этот tsx‑файл импортирует ModelExplorer.css, в котором определяются классы model‑explorer, model‑explorer‑title, model‑explorer‑item и так далее. Схема именования классов похожа на Яндекс БЭМ, только проще. В разных компонентах имена классов не пересекаются, потому что мы строго подходим к именованию компонентов, плюс их не на столько много.
Плюс у нас нет нужды генерить рандомные имена классов. Скорее наоборот, фиксированные имена классов упрощают тесты, нет необходимости добавлять дополнительные атрибуты в верстку типа data‑testid.
И собственно это и есть весь подход. Для каждого компонента tsx‑файл, css‑файл, возможно файл с тестами. Строгая схема именования компонентов и CSS‑классов. По возможности отсутствие зависимостей между компонентами. Есть файл, задающий цвета и общие стили. Точно нет нужды в миксинах или большом количестве переменных, потому что это добавляет зависимостей между CSS-файлами. Точно нет нужды в циклах или условиях, потому что это усложняет CSS.
Для меня такой подход максимально простой и удобный. Но я понимаю, что это не one‑size‑fits‑all solution.