Less и Sass называют препроцессорами CSS: вы пишете стили в файле .less или .scss с переменными, вложенными правилами и миксинами, а компилятор превращает его в обычный .css, который понимает браузер. Чтобы начать, хватит двух команд: npm install --save-dev sass и npx sass style.scss style.css (для Less нужны пакет less и команда lessc). Если вы пока путаетесь в самих каскадных таблицах, начните со статьи «Что такое CSS и как его использовать верстальщику»: препроцессор ускоряет работу, но знание CSS не заменяет.
Ниже разобраны установка, все основные возможности на примерах с реальным выводом компилятора, сравнение Sass и Less и ошибки, на которых чаще всего застревают новички. Примеры написаны для актуальных версий: Sass 1.108 и Less 4.9.
Что делает CSS-препроцессор

Препроцессор читает стили на своём языке и выдаёт готовый CSS. Браузер файл .scss или .less не откроет: в проект подключается только результат компиляции.
Языков три, и все решают одну задачу:
- Sass распространён больше остальных. У него два синтаксиса: SCSS (файлы
.scss, фигурные скобки и точки с запятой, как в CSS) и старый отступный синтаксис (файлы.sass, без скобок). Новичку стоит начинать с SCSS: его можно начать с обычного CSS и добавлять возможности по одной. - Less написан на JavaScript, синтаксис максимально близок к CSS. Переменные начинаются с
@, миксином служит любой класс. - Stylus третий по известности, разрешает писать без скобок, двоеточий и точек с запятой. Встречается заметно реже первых двух.
Что дают препроцессоры поверх CSS:
| Возможность | Зачем нужна | Sass | Less |
|---|---|---|---|
| Переменные | Цвет или отступ меняется в одном месте | $brand |
@brand |
| Вложенность | Стили компонента лежат одним блоком | есть | есть |
| Миксины | Повторяющийся набор свойств с параметрами | @mixin / @include |
.name() |
| Наследование | Несколько классов делят общие правила | @extend |
:extend() |
| Модули и импорт | Стили разбиты на файлы, в итоге один CSS | @use |
@import |
| Функции, условия, циклы | Цвета, расчёты, генерация классов | @if, @each, @for |
guards и рекурсивные миксины |
Нужен ли препроцессор, если в CSS уже есть переменные и вложенность
Часть того, ради чего препроцессоры появились, CSS умеет сам. Пользовательские свойства вида --brand: #2f6fde работают во всех современных браузерах, а вложенность с селектором & по данным MDN поддерживается всеми основными браузерами с декабря 2023 года.
Документация сборщика Vite прямо советует для проектов под современные браузеры писать на нативных переменных CSS и плагинах PostCSS. Поэтому перед тем как учить Sass, стоит понять, что вы получите сверх нативного CSS.
- Склейку селекторов. Запись
&__titleвнутри.cardв Sass и Less даёт класс.card__title. В нативной вложенности так нельзя: MDN пишет, что без комбинатора вложенный селектор считается селектором типа. Для БЭМ-вёрстки это главный довод в пользу препроцессора. - Миксины, циклы и условия. Сгенерировать двенадцать классов сетки или набор утилит одним циклом нативный CSS не умеет.
- Модули. Десятки файлов стилей превращаются в один CSS ещё до загрузки страницы, без цепочки запросов.
- Чужой код. Исходники Bootstrap написаны на Sass, и документация фреймворка предлагает настраивать его через переменные, карты и миксины Sass. В старых проектах часто живёт Less.
Переменные препроцессора и переменные CSS друг друга не заменяют. Переменная Sass исчезает при компиляции и в браузере уже не существует, а --brand можно поменять скриптом или медиазапросом прямо на странице. В реальных проектах их часто используют вместе.
Как установить Sass и Less и собрать первый CSS
Оба препроцессора ставятся через npm, поэтому сначала нужен Node.js. Если вы ещё не работали с ним, про стек и зачем он фронтенду рассказано в разборе профессии Node.js-разработчика.
Sass
- Откройте папку проекта в терминале и создайте
package.json:npm init -y. - Установите компилятор в зависимости разработки:
npm install --save-dev sass. В пакетеsassлежит Dart Sass, основная реализация языка. - Создайте файл
src/style.scssи напишите в нём любой CSS: обычный CSS уже корректный SCSS. - Скомпилируйте:
npx sass src/style.scss dist/style.css. Рядом появится и карта исходниковstyle.css.map, по ней инструменты разработчика в браузере показывают строку в.scss. - Чтобы не запускать команду после каждой правки, добавьте флаг
--watch: Sass будет пересобирать CSS при каждом сохранении. - Подключите к странице
dist/style.css, а не исходник. Как это делается, разобрано в инструкции «Как подключить CSS к HTML».
npm install --save-dev sass
npx sass src/style.scss dist/style.css
npx sass --watch src/style.scss dist/style.css
npx sass --style=compressed --no-source-map src/style.scss dist/style.min.css
Последняя команда собирает сжатый CSS без карты исходников, для продакшена. Из примера с переменными ниже она даёт одну строку:
.button{background:#2f6fde;border-radius:8px}
Less
- Установите компилятор:
npm install --save-dev less. Вместе с пакетом приходит командаlessc. - Создайте
style.less. - Скомпилируйте:
npx lessc style.less style.css. Без второго аргумента результат выводится в терминал.
Флага --watch у lessc нет. Пересборку при сохранении берёт на себя сборщик (Vite, webpack) или плагин редактора. Флаг сжатия -x пока работает, но выводит предупреждение:
The compress option has been deprecated. We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css.
.button{background:#2f6fde;border-radius:8px}
Less прямо в браузере через less.js
Less умеет компилироваться на странице: подключаете файл с rel="stylesheet/less" и скрипт less.js. Для учебного примера это удобно, но документация Less для продакшена советует заранее компилировать стили через Node.js или сторонние инструменты, когда важны скорость и надёжность.
Переменные в Sass и Less
Переменная хранит значение, которое повторяется по всему проекту: фирменный цвет, радиус скругления, шаг отступа. Поменяли в одном месте, и после компиляции новое значение оказалось во всех правилах.
Sass:
$brand: #2f6fde;
$radius: 8px;
.button {
background: $brand;
border-radius: $radius;
}
Less:
@brand: #2f6fde;
@radius: 8px;
.button {
background: @brand;
border-radius: @radius;
}
Оба файла компилируются в одинаковый CSS:
.button {
background: #2f6fde;
border-radius: 8px;
}
Разница только в знаке: в Sass переменная начинается с $, а в Less с @. Из-за этого в Less переменную легко спутать с директивами CSS вроде @media, хотя компилятор их различает. Если тема цвета в CSS для вас новая, загляните в инструкцию про цвет текста в HTML и CSS: там разобраны форматы, в которых удобно хранить палитру.
Вложенность и знак &
Вложенные правила повторяют структуру HTML: стили карточки, её заголовка и ссылок лежат в одном блоке. Знак & подставляет родительский селектор, поэтому &:hover превращается в a:hover, а &__title в .card__title.
.card {
padding: 16px;
&__title {
font-size: 20px;
}
a {
color: #2f6fde;
&:hover {
text-decoration: underline;
}
}
}
Этот фрагмент одинаково работает в Sass и Less и даёт такой CSS:
.card {
padding: 16px;
}
.card__title {
font-size: 20px;
}
.card a {
color: #2f6fde;
}
.card a:hover {
text-decoration: underline;
}
Удобство вложенности легко обернуть против себя. Каждый уровень добавляет селектор, и после четырёх-пяти уровней получается правило вроде .page .content .card .body a, которое трудно перебить. Ограничьтесь двумя-тремя уровнями и вкладывайте только то, что зависит от родителя. Как блоки на div собираются в разметку, показано в инструкции про тег div.
Миксины в CSS: повторяющиеся наборы свойств
Миксином называют именованный набор свойств, который можно вставить в любое правило, при желании с параметрами. Классический пример: центрирование через flexbox, которое нужно в кнопках, бейджах и панелях.
Sass объявляет миксин через @mixin, а вызывает через @include:
@mixin flex-center($gap: 8px) {
display: flex;
align-items: center;
justify-content: center;
gap: $gap;
}
.toolbar {
@include flex-center(12px);
}
.badge {
@include flex-center;
}
В Less миксином становится класс со скобками, вызов похож на вызов функции:
.flex-center(@gap: 8px) {
display: flex;
align-items: center;
justify-content: center;
gap: @gap;
}
.toolbar {
.flex-center(12px);
}
.badge {
.flex-center();
}
Правила на выходе одинаковые: у .toolbar зазор 12px, у .badge значение по умолчанию 8px.
.toolbar {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
}
.badge {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
Обратите внимание на скобки в объявлении Less. Обычный класс без скобок тоже можно вызвать как миксин, но тогда он попадёт в итоговый CSS отдельным правилом, а сам вызов без скобок (.flex-center;) Less 4.9 помечает как устаревший. Миксин со скобками в CSS не выводится. Для раскладок посложнее, чем одна строка, есть CSS Grid; пример адаптивной сетки без медиазапросов — в разборе auto-fill и auto-fit.
Наследование: @extend в Sass и :extend в Less
Миксин копирует свойства в каждое правило. Наследование работает иначе: компилятор дописывает нужные селекторы к общему правилу, и свойства в CSS не дублируются.
В Sass для этого есть селекторы-заготовки с %, они сами в CSS не попадают:
%message {
padding: 12px;
border: 1px solid #ccc;
}
.success {
@extend %message;
border-color: green;
}
.error {
@extend %message;
border-color: red;
}
Компилятор Sass собрал общие свойства под двумя классами, а %message в вывод не вошёл:
.error, .success {
padding: 12px;
border: 1px solid #ccc;
}
.success {
border-color: green;
}
.error {
border-color: red;
}
В Less то же делает псевдокласс :extend(), но наследоваться приходится от обычного класса:
.message {
padding: 12px;
border: 1px solid #ccc;
}
.success:extend(.message) {
border-color: green;
}
.error:extend(.message) {
border-color: red;
}
.message,
.success,
.error {
padding: 12px;
border: 1px solid #ccc;
}
.success {
border-color: green;
}
.error {
border-color: red;
}
Здесь класс .message остался в CSS, потому что он настоящий. Наследование удобно для вариантов одного компонента: сообщений, кнопок, плашек. Рамки в этих примерах заданы свойством border, его стили и сокращённая запись разобраны в отдельной инструкции про border.
Модули, импорт и встроенные функции
Большой проект хранит стили в десятках файлов: переменные, сетка, компоненты. Препроцессор собирает их в один CSS.
@use вместо @import в Sass
В Sass файл с префиксом _ (например, _colors.scss) считается частью и отдельным CSS не компилируется. Подключать его нужно через @use, а переменные вызывать с именем модуля:
// _colors.scss
$brand: #2f6fde;
// use.scss
@use "colors";
.link {
color: colors.$brand;
}
.link {
color: #2f6fde;
}
Старый @import пока работает, но в Dart Sass с версии 1.80.0 он объявлен устаревшим, и компилятор пишет предупреждение:
DEPRECATION WARNING [import]: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0.
More info and automated migrator: https://sass-lang.com/d/import
╷
1 │ @import "colors";
│ ^^^^^^^^
╵
import.scss 1:9 root stylesheet
Удалить @import разработчики планируют только в Dart Sass 3.0.0. Для перевода старых стилей есть официальная утилита sass-migrator. В Less @import остаётся основным способом: @import "colors"; подключит colors.less.
Функции цвета и математика
Оба препроцессора умеют затемнять и осветлять цвет, считать проценты и размеры. В Less функции вызываются напрямую:
@brand: #2f6fde;
.button:hover {
background: darken(@brand, 10%);
}
.col {
width: percentage((1 / 3));
}
.button:hover {
background: #1e58bc;
}
.col {
width: 33.33333333%;
}
В современном Sass функции живут в модулях sass:color и sass:math:
@use "sass:color";
@use "sass:math";
$brand: #2f6fde;
.button:hover {
background: color.adjust($brand, $lightness: -10%);
}
.col {
width: math.percentage(math.div(1, 3));
}
.button:hover {
background: rgb(11.706126434%, 34.4089170938%, 73.7840696445%);
}
.col {
width: 33.3333333333%;
}
Sass 1.108.1 вывел затемнённый цвет в формате rgb() с дробными процентами, а Less шестнадцатеричным кодом. Браузеру годятся оба варианта.
Привычные по старым урокам darken($brand, 10%) и деление через косую черту 100px / 3 Sass ещё компилирует, но на каждую такую строку выдаёт предупреждение с готовой заменой:
DEPRECATION WARNING [global-builtin]: Global built-in functions are deprecated and will be removed in Dart Sass 3.0.0.
Use color.adjust instead.
More info and automated migrator: https://sass-lang.com/d/import
╷
4 │ background: darken($brand, 10%);
│ ^^^^^^^^^^^^^^^^^^^
╵
old.scss 4:15 root stylesheet
DEPRECATION WARNING [color-functions]: darken() is deprecated. Suggestions:
color.scale($color, $lightness: -18.9591078067%)
color.adjust($color, $lightness: -10%)
More info: https://sass-lang.com/d/color-functions
╷
4 │ background: darken($brand, 10%);
│ ^^^^^^^^^^^^^^^^^^^
╵
old.scss 4:15 root stylesheet
DEPRECATION WARNING [slash-div]: Using / for division outside of calc() is deprecated and will be removed in Dart Sass 2.0.0.
Recommendation: math.div(100px, 3) or calc(100px / 3)
More info and automated migrator: https://sass-lang.com/d/slash-div
╷
5 │ width: (100px / 3);
│ ^^^^^^^^^
╵
old.scss 5:11 root stylesheet
Условия и циклы
В Sass для этого есть обычные @if / @else и циклы @each, @for и @while. Пример ниже генерирует три класса размера текста и выбирает тему по параметру миксина. Сами единицы и способы задать font-size разобраны в инструкции про размер текста в HTML и CSS.
@each $name, $size in (sm: 12px, md: 16px, lg: 20px) {
.text-#{$name} {
font-size: $size;
}
}
@mixin theme($dark: false) {
@if $dark {
background: #111;
color: #fff;
} @else {
background: #fff;
color: #111;
}
}
.page {
@include theme($dark: true);
}
В Less нет операторов if и for. Условие записывается «охранником» when у миксина, а цикл записывается миксином, который вызывает сам себя:
.text-sizes(@i: 1) when (@i <= 3) {
@name: extract(sm md lg, @i);
@size: extract(12px 16px 20px, @i);
.text-@{name} {
font-size: @size;
}
.text-sizes(@i + 1);
}
.text-sizes();
.theme(@dark) when (@dark = true) {
background: #111;
color: #fff;
}
.theme(@dark) when (default()) {
background: #fff;
color: #111;
}
.page {
.theme(true);
}
Оба файла дают одинаковые правила:
.text-sm {
font-size: 12px;
}
.text-md {
font-size: 16px;
}
.text-lg {
font-size: 20px;
}
.page {
background: #111;
color: #fff;
}
Цикл на Less читать сложнее: он спрятан в рекурсии, а элементы списка достаются функцией extract(). На простых проектах это не мешает, а в библиотеке утилит с десятками циклов рекурсивные миксины разбирать заметно труднее.
Sass или Less: что выбрать

Разница в возможностях сводится к таблице:
| Критерий | Sass (SCSS) | Less |
|---|---|---|
| Синтаксис | SCSS как CSS, плюс старый отступный | как CSS |
| Переменные | $name |
@name |
| Условия и циклы | @if, @each, @for, @while |
guards when и рекурсия |
| Модули | @use с пространством имён |
@import |
| Компилятор | Dart Sass, режим --watch встроен |
lessc на JavaScript, без --watch |
| Работа в браузере | нет | есть, через less.js |
| Скачивания npm за 1–7 ноября 2026 | около 43,4 млн (пакет sass) |
около 14,6 млн |
Цифры скачиваний взяты из открытого API npm (данные по Less взяты тем же запросом). В них входят и автоматические установки в сборках, поэтому это мера распространённости пакета, а не число людей. Ещё около 10,2 млн скачиваний за ту же неделю у пакета sass-embedded, второго варианта компилятора Sass, а у Stylus около 3,8 млн.
Практический ответ такой:
- Учитесь с нуля: берите SCSS. На нём написан Bootstrap (команда фреймворка перешла с Less на Sass ещё в четвёртой версии, об этом сказано в анонсе Bootstrap 4 alpha).
- Пришли в проект на Less: пишите на Less. Переписывать рабочие стили ради другого препроцессора нет смысла, а основы у них общие: переменные, вложенность, миксины переносятся почти один к одному.
- Небольшой сайт под современные браузеры можно сверстать и на нативных переменных и вложенности CSS, без компиляции.
Если вы выбираете фреймворк для первой страницы, посмотрите разбор «Bootstrap: что это за фреймворк»: настройка его темы как раз идёт через переменные Sass.
Как подключить препроцессор к Vite и webpack
В рабочем проекте компилятор редко запускают руками: стили собирает сборщик вместе с JavaScript.
Vite поддерживает файлы .scss, .sass, .less, .styl и .stylus из коробки, плагины не нужны. По документации Vite достаточно поставить сам препроцессор:
# .scss и .sass
npm add -D sass-embedded # или sass
# .less
npm add -D less
После этого можно импортировать ./style.scss прямо из JavaScript-файла.
webpack требует загрузчик: sass-loader для Sass и less-loader для Less. Пример из документации less-loader использует встроенную поддержку CSS, которая нужна webpack 5.87.0 или новее:
npm install less less-loader --save-dev
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
type: "css/auto",
use: ["less-loader"],
},
],
},
experiments: {
css: true,
},
};
Для Sass конфигурация та же, только в test стоит /\.s[ac]ss$/i, в use стоит "sass-loader", а ставятся пакеты sass-loader sass webpack, как указано в документации sass-loader.
Частые ошибки и что с ними делать

Большинство проблем новичков повторяются. Ниже симптом, причина и решение, с настоящими сообщениями компиляторов.
1. Стили не применились, хотя файл сохранён. В HTML подключён style.scss или style.less, а браузер такой файл не понимает.
Решение: подключайте скомпилированный style.css и проверьте, что компиляция запускалась (--watch в Sass или сборщик для Less).
2. Правки в CSS пропадают. Вы исправили dist/style.css руками, а следующая сборка перезаписала файл.
Решение: правьте только исходник, а папку с результатом добавьте в .gitignore или хотя бы договоритесь в команде её не трогать.
3. «Undefined variable» в Sass. Переменная объявлена в другом файле, который не подключён, или подключён через @use, а вызывается без имени модуля.
Error: Undefined variable.
╷
2 │ color: $brand;
│ ^^^^^^
╵
undef.scss 2:10 root stylesheet
Решение: добавьте @use "colors"; и пишите colors.$brand.
4. «variable @brand is undefined» в Less. Та же причина: нет @import файла с переменными или опечатка в имени. Путь к файлу в выводе ниже сокращён до имени.
NameError: variable @brand is undefined in undef.less on line 2, column 10:
1 .link {
2 color: @brand;
3 }
5. Ошибка expected ";" в Sass. Пропущена точка с запятой в предыдущей строке, а компилятор указывает на место, где разбор не смог продолжиться, то есть на строку ниже.
Error: expected ";".
╷
3 │ margin: 0;
│ ^
╵
semi.scss 3:9 root stylesheet
Решение: смотрите на строку выше той, что указана в сообщении.
6. Предупреждения DEPRECATION WARNING на старом коде. CSS при этом собирается. Но @import, глобальные darken() и lighten(), деление через / перестанут работать в будущих версиях Dart Sass.
Решение: замените их по подсказке из предупреждения или прогоните стили через sass-migrator.
Где освоить вёрстку системно
Сам препроцессор учится быстро, если вы уверенно знаете CSS: адаптивность, сетки, каскад и специфичность. Без этой базы Sass и Less только прячут ошибки за красивым синтаксисом.
Если хочется пройти путь от разметки до сборки проекта с наставником, сравните курсы по вёрстке и фронтенд-разработке. Чем занимаются специалисты на выходе, описано в разборах профессий HTML-верстальщика и фронтенд-разработчика.
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| Веб-вёрстка Перейти на сайт курса | 145 989 ₽ | 2818 ₽/мес. | 3 месяца | Обзор курса | |
| Основы вёрстки HTML и CSS Перейти на сайт курса | 32 676 ₽ | 2723 ₽/мес. | 3 месяца | Обзор курса | |
| HTML и CSS. Адаптивная вёрстка и автоматизация Перейти на сайт курса | 23 400 ₽ | 3900 ₽/мес. | 2 месяца | Обзор курса | |
| Типографика и верстка: внимание к тексту Перейти на сайт курса | 43 400 ₽ | 6391 ₽/мес. | 12 месяцев | Обзор курса | |
| Графический дизайн: основы верстки и фирменный стиль Перейти на сайт курса | 52 220 ₽ | 5120 ₽/мес. | 4 месяца | Обзор курса |
Больше программ — в полном каталоге курсов по вёрстке




