Tailwind отлично работает на маленьких проектах. На больших — без правил быстро превращается в кашу из 25 классов на каждом div. Расскажу, как мы держим Tailwind в порядке на проектах в 200+ компонентов.
Дизайн-токены через CSS-переменные
Не пишите цвета напрямую (bg-blue-500, text-gray-900). Вынесите в CSS-переменные через Tailwind config:
theme: {
extend: {
colors: {
bg: "var(--bg)",
fg: "var(--fg)",
primary: "var(--primary)",
"primary-fg": "var(--primary-fg)",
}
}
}
В globals.css объявляете --bg, --fg, --primary для светлой темы. Это даёт два преимущества: легко менять палитру централизованно, и поддержка тем (если когда-нибудь понадобятся).
Радиусы, тени, шрифтовые шкалы — туда же. Стандартные rounded-lg заменяются на rounded-[var(--radius)] или семантические rounded-card.
cn() и tailwind-merge
clsx плюс tailwind-merge — must have. Создаёте утилиту cn():
import { twMerge } from "tailwind-merge";
import { clsx } from "clsx";
export function cn(...inputs) {
return twMerge(clsx(inputs));
}
Используете везде, где нужно условно склеить классы:
<div className={cn("p-4", isActive && "bg-primary", className)} />
tailwind-merge решает конфликты: если в дефолтных классах был p-4, а пробросили p-6 — он уберёт первый. Без этого — классы накладываются непредсказуемо.
Компоненты вместо длинных классов
Если у вас в коде 5 раз повторяется flex items-center justify-between gap-3 px-4 py-2 rounded-md border border-border bg-bg-card hover:bg-bg-subtle transition-colors — это компонент Card, а не разметка.
shadcn/ui или собственная библиотека UI-компонентов — основа. Уровни абстракции: примитивы (Button, Input, Card), составные (Form, Modal, Sidebar), фичи (ProductCard, OrderSummary).
@apply: использовать или нет
Спорный вопрос. Tailwind официально не рекомендует @apply для всего, но в реальных проектах он удобен для трёх случаев:
- Утилиты, которые часто повторяются (
.card,.section-padding) — в@layer components. - Стилизация сторонних компонентов, к которым нет прямого доступа.
- Адаптация классов из дизайн-системы под маркетинговые секции.
Не злоупотребляйте: @apply всё равно компилируется в обычный CSS, и преимущества Tailwind (atomic CSS, минимальный размер) теряются.
Сортировка классов
prettier-plugin-tailwindcss — подключите. Он сортирует классы в едином порядке (layout → spacing → sizing → typography → colors → effects). Code review становится проще, конфликтов меньше.
Без сортировки порядок классов внутри строк хаотичен, и cn("p-4 bg-red", className) ведёт себя по-разному при разных порядках.
Темы и режимы
Если нужны темы — делайте через CSS-переменные плюс data-theme:
[data-theme="dark"] {
--bg: 18 18 22;
--fg: 240 240 240;
}
Не используйте Tailwind dark: префикс на всех компонентах — это усложняет разметку и фиксирует дуальность. С CSS-переменными можно поддержать сколько угодно тем без изменений в компонентах.
Производительность сборки
Tailwind v3+ компилирует только используемые классы. На проекте 200 компонентов финальный CSS обычно 30-80 КБ (gzipped: 8-15 КБ). Это нормально.
Что замедляет сборку: широкие шаблоны в content (например, **/*.tsx в monorepo с тысячами файлов). Указывайте конкретные пути. Используйте Tailwind v4 с новым движком — он быстрее v3 в 2-5 раз на больших проектах.
Линтинг и ESLint
Подключите eslint-plugin-tailwindcss. Он ловит несуществующие классы, неправильные модификаторы, неиспользуемые negative-классы. Это не критично, но снимает класс ошибок.
Также полезно правило, ограничивающее количество классов на одном элементе. Если на div больше 15 классов — это сигнал к рефакторингу в компонент.
Итого
Tailwind на большом проекте — это дизайн-токены через CSS-переменные, cn-утилита с tailwind-merge, компонентная архитектура и автоматизация сортировки. Без этого через год Tailwind становится главным антипаттерном проекта. С этим — основа быстрой и поддерживаемой разработки.
Частые вопросы
Как организовать дизайн-токены в Tailwind?
Не пишите цвета напрямую (bg-blue-500, text-gray-900). Вынесите в CSS-переменные через Tailwind config: theme.extend.colors с bg: "var(--bg)", primary: "var(--primary)" и т.д. В globals.css объявляете --bg, --fg, --primary для светлой темы. Это даёт два преимущества: легко менять палитру централизованно, и поддержка тем (если когда-нибудь понадобятся). Радиусы, тени, шрифтовые шкалы — туда же. Стандартные rounded-lg заменяются на rounded-[var(--radius)] или семантические rounded-card.
Зачем нужна утилита cn() с tailwind-merge?
clsx плюс tailwind-merge — must have. Создаёте утилиту cn(), используете везде, где нужно условно склеить классы. tailwind-merge решает конфликты: если в дефолтных классах был p-4, а пробросили p-6 — он уберёт первый. Без этого классы накладываются непредсказуемо. Это особенно важно при работе с переиспользуемыми компонентами, которые принимают className пропсом — без cn() пользователь компонента не сможет переопределить стили предсказуемо.
Когда выносить Tailwind-классы в компонент?
Если у вас в коде 5 раз повторяется flex items-center justify-between gap-3 px-4 py-2 rounded-md border border-border bg-bg-card hover:bg-bg-subtle transition-colors — это компонент Card, а не разметка. shadcn/ui или собственная библиотека UI-компонентов — основа. Уровни абстракции: примитивы (Button, Input, Card), составные (Form, Modal, Sidebar), фичи (ProductCard, OrderSummary). Когда на div больше 15 классов — это сигнал к рефакторингу в компонент.
Стоит ли использовать @apply в Tailwind?
Спорный вопрос. Tailwind официально не рекомендует @apply для всего, но в реальных проектах он удобен для трёх случаев. Утилиты, которые часто повторяются (.card, .section-padding) — в @layer components. Стилизация сторонних компонентов, к которым нет прямого доступа. Адаптация классов из дизайн-системы под маркетинговые секции. Не злоупотребляйте: @apply всё равно компилируется в обычный CSS, и преимущества Tailwind (atomic CSS, минимальный размер) теряются. Используйте точечно.
Как реализовать темы (светлая/тёмная) на Tailwind?
Через CSS-переменные плюс data-theme. В CSS объявляете [data-theme="dark"] { --bg: 18 18 22; --fg: 240 240 240; }. Не используйте Tailwind dark: префикс на всех компонентах — это усложняет разметку и фиксирует дуальность. С CSS-переменными можно поддержать сколько угодно тем без изменений в компонентах. Просто переопределяете переменные в data-theme, и весь UI автоматически перерисовывается. Это удобнее для масштабирования и для добавления новых тем.
Что важно знать о производительности Tailwind в больших проектах?
Tailwind v3+ компилирует только используемые классы. На проекте 200 компонентов финальный CSS обычно 30-80 КБ (gzipped: 8-15 КБ). Это нормально. Что замедляет сборку: широкие шаблоны в content (например, **/*.tsx в monorepo с тысячами файлов). Указывайте конкретные пути. Используйте Tailwind v4 с новым движком — он быстрее v3 в 2-5 раз на больших проектах. Подключите prettier-plugin-tailwindcss для автоматической сортировки классов и eslint-plugin-tailwindcss для линтинга.