Раньше в Sass был только @import, который просто копировал содержимое одного файла в другой. Это создавало проблемы: глобальное загрязнение, конфликты имён, дублирование кода.@use и @forward появились несколько лет назад, но только сейчас, с приближением выхода Dart Sass 3.0.0, @import официально объявлен устаревшим и будет полностью удалён. В связи с этим стоит разобраться с модульной системой, если вы её до сих пор обходили стороной.
1. @use — подключение модуля
@use загружает файл (модуль) и делает его содержимое доступным в текущем файле, но в изолированном пространстве имён. Это главное отличие от @import.
@use 'путь/файл';
По умолчанию все переменные, миксины и функции из загруженного файла становятся доступны через пространство имён, равное последней части пути (без подчёркивания и расширения).
Пример:
$primary: blue; $secondary: gray;
Подключаем в body/header.scss:
@use '../helpers/colors'; .button { color: colors.$primary; //обращение через пространство имён "colors" }
Важно: пространство имён по умолчанию берётся из названия файла.
2. Изменение пространства имён (as)
Можно задать своё имя для модуля, чтобы сократить или уточнить контекст:
@use 'helpers/colors' as myColors; .button { color: myColors.$primary; //обращение через "myColors" }
Пространства имён в Sass — это идентификаторы, они подчиняются тем же правилам, что и имена переменных:
✅ МОЖНО:
буквы a–z, A–Z
цифры 0–9 (но не в начале)
camelCase (myColors)
PascalCase (MyColors)
❌ НЕЛЬЗЯ:
дефис (-)
пробелы
спецсимволы (!@#$%^&*)
начинаться с цифры
3. Встроенные модули (math, list, map, color, string)
Sass предоставляет встроенные модули, которые подключаются через @use с префиксом sass::
@use 'sass:math'; @use 'sass:list'; @use 'sass:map'; @use 'sass:color'; @use 'sass:string';
Примеры:
$width: math.div(100%, 3); //деление $len: list.length($my-list); //длина списка $color: color.adjust(#336699, $lightness: 20%); $index: string.index($string, 'sub');
Важно: встроенные модули нужно подключать в каждом файле, где используются их функции. Они не наследуются через другие импорты.
4. Использование миксинов и функций из модулей
Миксины и функции, определённые в пользовательских файлах, тоже доступны через пространство имён:
// helpers/_mixins.scss @mixin flex-center { display: flex; align-items: center; justify-content: center; }
// components/_card.scss @use '../helpers/mixins'; .card { @include mixins.flex-center; }
Если нужно импортировать несколько модулей в одном файле, делаем это явно:
@use '../helpers/colors'; @use '../helpers/variables' as var; @use '../helpers/mixins';
5. Организация файлов
Каждый SCSS-файл сам отвечает за свои зависимости. В начале файла перечисляются все необходимые модули с помощью @use. Это обеспечивает полную прозрачность и упрощает рефакторинг.
Рекомендуемая структура папок:
scss/ helpers/ _colors.scss _variables.scss _mixins.scss components/ _button.scss _card.scss pages/ _about-page.scss template.scss
Пример components/_button.scss:
@use '../helpers/colors' as myColors; @use '../helpers/variables'; @use '../helpers/mixins'; .button { background-color: myColors.$primary; padding: variables.$spacing-md; @include mixins.border-radius; }
6. Преимущества подхода с пространством имён
Явность — сразу видно, из какого модуля взята переменная/миксин.
Отсутствие конфликтов — даже если в разных модулях есть одинаковые имена, они не пересекаются.
Лёгкий рефакторинг — можно менять один модуль, не боясь сломать другие.
Поддержка IDE — автодополнение работает лучше, так как пространства имён известны.
Масштабируемость — код остаётся понятным даже в больших проектах.
7. Важные замечания
@use работает только в начале файла (до любых правил).
Один и тот же модуль можно использовать в нескольких файлах, каждый раз подключая его явно.
Встроенные модули не нужно копировать в проект — они уже есть в Sass. Их нужно явно подключать в необходимом файле:
@use '../helpers/colors' as myColors; @use '../helpers/variables'; @use '../helpers/mixins'; @use 'sass:list'; .button { background-color: myColors.$primary; padding: variables.$spacing-md; @include mixins.border-radius; $len: list.length($my-list; //длина списка }
8. @use ... with ()
@use ... with () — это механизм конфигурации модулей в Sass. Он позволяет передавать значения в модуль при его импорте, переопределяя переменные, которые помечены как !default.
8.1 Как это работает:
В модуле объявляются переменные с !default
// helpers/_theme.scss $bg-color: #ffffff !default; //значение по умолчанию $text-color: #333333 !default; //можно переопределить $spacing-unit: 8px !default; //можно переопределить $border-radius: 4px !default; //можно переопределить
!default означает: «используй это значение, если никто не передал своё»:
Если значение НЕ БЫЛО задано до импорта — используется то, что после !default
Если значение УЖЕ БЫЛО задано — используется заданное, а значение после !default игнорируется
Пример, когда значение было задано ДО импорта:
// helpers/_theme.scss $bg-color: #ffffff !default; //будет белый, если никто не задал другой
// pages/about-page.scss$bg-color: #000000; //задали чёрный ДО импорта @use 'helpers/theme'; body { background: theme.$bg-color; //будет #000000 }
8.2 При импорте передаём новые значения через with:
// pages/dark-theme.scss @use '../helpers/theme' with ( $bg-color: #1a1a1a, $text-color: #f0f0f0, $spacing-unit: 12px ); body { background: theme.$bg-color; //будет #1a1a1a color: theme.$text-color; //будет #f0f0f0 padding: theme.$spacing-unit; //будет 12px border-radius: theme.$border-radius; // будет 4px (осталось по умолчанию) }
Выходит, что с помощью @use ... with(), мы также переопределяем переменные, только вместо "ДО импорта", мы прописываем с помощью with в скобках самого импорта.
Таким образом, у нас есть два способа переопределить переменные в конкретном файле
Сделать это до конкретного импорта, а лучше вышел всех импортов в файле .scss
Переопределить переменную из определенного импорта, используя with()
8.3 Примечание
Многие Sass-библиотеки используют !default для настройки своих стилей. Их также можно переопределить двумя способами, указанными выше (если такое требуется).
Для одного и того же модуля директива with() работает только при первом импорте. Все последующие @use ... with() для этого же модуля будут проигнорированы:
// Правильно @use 'helpers/theme' with ( $bg-color: #000 ); // Бесполезно (повторный импорт игнорирует with) @use 'helpers/theme' with ( $bg-color: #f00 //НЕ СРАБОТАЕТ! );
Можно применять @use... with() для каждого импорта (но не для одного и того же повторно):
// helpers/colors // Правильно @use 'helpers/colors' with ( $primary: red, $secondary: lightgray ); // helpers/spacing // Правильно @use 'helpers/spacing' with ( $padding: 24px, $margin: 12px );
9. @forward — проброс модуля
@forward — это директива, которая передаёт содержимое подключённых файлов дальше, но сама не даёт к ним доступ в текущем файле. Она используется для создания единой точки входа (публичного API) из нескольких модулей.
9.1 Что делает @forward?
@forward полезен тем, что его можно использовать в одном scss файле, который можно импортировать в scss файлах и при этом не прописывать несколько штук импортов в каждом файле.
Пример с @forward:
Создаем scss файл, допустим _core.scss, и прописываем в нем ссылки, с помощью @forward, на scss файлы, которые являются для нас глобальными (переменные, цвета, миксины, шрифты, базовые стили и прочее)
// core.scss @forward "helpers/colors"; @forward "helpers/variables"; @forward "base/fonts"; @forward "helpers/fonts-variables"; @forward "helpers/extend"; @forward "base/reset"; @forward "base/reboot"; @forward "base/base"; @forward "base/new-system";
И дальше добавляем только один импорт в scss файлах:
//./pages/about-page.scss @use "../core.scss";
Плюс в том, что вместо, например, 9 импортов, мы будем использовать только один "core".
НО минус такого подхода состоит в том, что при использовании пространства имен (неймспейс), мы не сможем точно определить из какого scss файла нужная нам переменная, так как все неймспейсы будут равны имени одного файла (c @forward) или же назначенному нами имени (через as). Итог с @forward:
// ./pages/about-page.scss @use "../core.scss"; //или @use "../core.scss" as core; .button { color: core.$blue; border-radius: core.$border-radius-medium; @include core.flex-center; }
Без @forward удобнее тем, что мы сразу можем определить из какого файла, нужный нам стиль, как было описано выше. Но вот еще пример:
// ./pages/about-page.scss @use '../helpers/colors'; @use '../helpers/variables'; @use '../helpers/mixins'; .button { color: color.$blue; border-radius: variables.$border-radius-medium; @include mixins.flex-center; }
9.2 Важный нюанс
Как уже говорилось, @forward только пробрасывает содержимое дальше, но сам файл, в котором написаны @forward, не получает доступа к этим переменным и миксинам. Если внутри _core.scss понадобится использовать что-то из проброшенных файлов, нужно добавить отдельный @use.
// _core.scss @forward 'helpers/colors; //проброс наружу @use 'helpers/colors' as c; //для использования внутри body { background: c.$bg-color; //работает благодаря @use }
9.3 Пространство имён при использовании @forward
При импорте файла-сборщика через @use пространство имён определяется так же, как и для обычного модуля.
9.4 Выборочный проброс (show / hide)
С помощью show и hide можно ограничить, что именно пробрасывается из модуля:
show — пробросить только перечисленные имена
hide — пробросить всё, кроме перечисленных
// helpers/_index.scss @forward 'colors' show $primary, $secondary; //только эти переменные @forward 'mixins' hide private-mixin; //все, кроме private-mixin
9.5 Конфигурация через with() при пробросе
Если пробрасываемый файл содержит переменные с !default, их можно переопределить прямо в @forward с помощью with():
// helpers/_theme.scss $bg-color: #fff !default; $text-color: #000 !default; // helpers/_index.scss @forward 'theme' with ( $bg-color: #f0f0f0, $text-color: #222 );
10. Как организовывать зависимости между модулями
В модульной системе Sass каждый файл изолирован и должен явно указывать, откуда он берёт переменные, миксины и функции. Это касается и случаев, когда один ваш модуль (например, variables.scss) использует переменные из другого модуля (colors.scss).
Пример: variables.scss зависит от colors.scss
// _core.scss @forward 'helpers/colors'; @forward 'helpers/variables'; @forward 'helpers/mixins';
Внутри _variables.scss по-прежнему нужно писать:
//variables.scss @use 'colors; //явная зависимость // ...
Почему это правильно:
Явность – сразу видно, от каких модулей зависит файл.
Надёжность – при переносе файла в другое место зависимости не теряются.
Поддержка IDE – автодополнение работает чётко.
Рефакторинг – легко найти все места, использующие конкретный модуль.
11. Краткие итоги
Явность важнее краткости – каждый файл сам импортирует нужные модули через @use. Это делает зависимости прозрачными.
Пространство имён обязательно – обращайся к переменным/миксинам через имя модуля (или алиас). Никакого глобального доступа.
Имена модулей – только буквы, цифры (не в начале). Дефисы и спецсимволы запрещены.
Встроенные модули (sass:math, sass:list и др.) подключаются там, где используются. Они не наследуются.
Конфигурация через !default и with() – позволяет гибко настраивать модули, переопределяя значения по умолчанию. with() работает только при первом импорте.
@forward для сборки – удобен для создания единой точки входа, но скрывает источник переменных. Используй осознанно.
show / hide в @forward – позволяют точечно контролировать, что попадает в публичное API.
Зависимости внутри модулей – даже если файл входит в сборщик, внутри него нужно явно писать @use для других модулей.
Повторные импорты – норма. Даже если один модуль нужен в ста файлах, в каждом пишем @use. Это плата за надёжность.
Рефакторинг становится безопасным – изменения в одном модуле не ломают другие, если их имена не конфликтуют.
12. Глобальный подход (который не стоит использовать, но о котором стоит просто знать)
В документации я описал @use ... as для создания псевдонима модуля. Но существует ещё один вариант: @use ... as * .
@use 'helpers/colors' as *;
as * импортирует модуль в глобальное пространство имён. Переменные, миксины и функции становятся доступны без префикса — как в старом добром import.
Возвращает те самые проблемы, от которых уходили — конфликты имён, глобальное загрязнение, неявные зависимости.
Ломает прозрачность кода — глядя на $primary, невозможно понять, из какого модуля эта переменная.
Рефакторинг становится опасным — удаление или переименование модуля может сломать код в неочевидных местах.
Сам Dart Sass не рекомендует этот подход — он оставлен только для плавного перехода с import, но не для использования в новой кодовой базе.
Итог: as * — это лазейка из прошлого. Если вы пишете код с нуля или мигрируете проект осознанно, используйте обычные пространства имён. Явность важнее краткости.
