Фаза 1. Сканирование
Tailwind обходит дерево проекта от корня и читает файлы как обычный
текст. Он не разбирает JavaScript, не выполняет шаблоны и не строит DOM —
он ищет подстроки, похожие на имена утилит. Пропускаются каталоги из
.gitignore (в том числе node_modules) и бинарные файлы.
Из этого следует правило, которое стоит запомнить раз и навсегда:
Сканер похож на корректора, который ищет в рукописи упоминания городов, чтобы напечатать для книги только нужные карты. Он читает буквы. Если в тексте написано «столица» вместо «Париж», карту Парижа он не напечатает — догадываться не его работа.
Как расширить область сканирования
Иногда разметка живёт там, куда автоопределение не заглядывает: в пакете
из node_modules, в каталоге, игнорируемом гитом, в шаблонах бэкенда.
Тогда источники указывают явно:
@import "tailwindcss";
/* добавить каталог к сканированию */
@source "../node_modules/@my-company/ui-kit/dist";
/* исключить каталог */
@source not "./src/legacy";
/* сгенерировать классы, которых нет в коде (например, приходят с сервера) */
@source inline("underline font-bold text-emerald-600");
Есть и обратный приём: @import "tailwindcss" source(none);
полностью отключает автоопределение — тогда сканируется только то, что вы
перечислили сами. Так собран и CSS для демонстраций этого курса.
Фаза 2. Генерация: откуда берутся значения
Найдя p-4, движок не ищет готовое правило в библиотеке — он
вычисляет его из темы:
/* тема задаёт базовый шаг */
--spacing: 0.25rem;
/* утилита получается умножением */
.p-4 { padding: calc(var(--spacing) * 4); }
То же и с цветами: bg-slate-900 подставляет значение переменной
--color-slate-900. Поэтому изменение темы меняет сразу все утилиты,
которые из неё выведены.
Фаза 3. Слои и сила правил
Готовый CSS раскладывается по каскадным слоям в фиксированном порядке:
@layer theme, base, components, utilities;
- theme — переменные темы;
- base — preflight: сброс отступов,
box-sizing, списки без маркеров, изображения как блочные элементы; - components — место для ваших компонентных классов;
- utilities — утилиты.
Слои решают вечную проблему специфичности: правило из utilities
всегда сильнее правила из base, даже если селектор base выглядит
«сильнее». А любой ваш CSS, написанный вне слоёв, окажется сильнее
утилит — и это самая частая причина «мой класс перебивает Tailwind».
@layer components —
тогда утилиты смогут его переопределить, как и задумано.Тема: одна переменная — семейство утилит
Блок @theme — это не «настройки», а объявление токенов.
Каждое пространство имён отвечает за свою группу утилит:
/* src/style.css */
@import "tailwindcss";
@theme {
--color-brand-500: oklch(0.55 0.21 264);
--spacing-huge: 7.5rem;
--breakpoint-tablet: 60rem;
}
После такой темы в проекте появляются bg-brand-500,
text-brand-500, border-brand-500, ring-brand-500,
отступ p-huge и вариант tablet: — без единой строчки
дополнительного кода. Заодно значения доступны как обычные CSS-переменные:
var(--color-brand-500).
Вот тот же приём, применённый в этом курсе: у демонстраций есть собственный
токен --brand, и он работает как обычный цвет темы.
<div class="flex flex-wrap items-center gap-3">
<span class="rounded-md bg-brand px-3 py-1.5 text-sm font-medium text-brand-foreground">bg-brand</span>
<span class="rounded-md border border-brand px-3 py-1.5 text-sm text-brand">border-brand</span>
<span class="text-sm font-semibold text-brand">text-brand</span>
</div>
Сброс и замена шкал
Тема не только дополняется, но и урезается. Запись со звёздочкой очищает целое пространство имён — удобно, когда в проекте должна остаться только фирменная палитра:
@theme {
--color-*: initial; /* убрать всю палитру по умолчанию */
--color-white: #fff;
--color-ink: oklch(0.2 0 0);
}
После этого bg-red-500 просто не существует — движок его не
сгенерирует. Это осознанный приём для дизайн-систем: «нельзя случайно
использовать цвет вне палитры».
Как посмотреть, что получилось
- DevTools → Styles: выберите элемент и увидите готовое правило утилиты вместе с подставленными значениями.
- Поиск по итоговому CSS: соберите файл и найдите в нём класс — если его нет, значит, сканер его не увидел.
- Вкладка Computed: показывает финальное значение свойства, если несколько правил спорят между собой.
--color-*, --spacing,
--font-*, --text-*, --radius-*,
--shadow-*, --breakpoint-*, --container-*,
--ease-*, --animate-*) со временем пополняется —
актуальный список смотрите в разделе Theme variables документации.