Роками дизайн-токени в Tailwind жили у величезному tailwind.config.js — JavaScript-об'єкті, який дизайнер боявся відкривати, а розробник копіпастив із Figma вручну. Tailwind v4 це прибрав. Тепер токени описуються прямо в CSS через директиву @theme, а фреймворк на Rust-движку читає їх і генерує утиліти на льоту.
Для дизайнера, що вчиться кодити, це найкраща новина за останні роки: між твоїми змінними у Figma і класами у коді тепер лежить один CSS-файл, а не чорна скринька конфіга. Розберемо, як це працює і як побудувати єдине джерело правди для токенів.
Що насправді змінилось у v4
Головна зміна — CSS-first конфігурація. У Tailwind v3 усе налаштування (кольори, spacing, шрифти, радіуси) описувалось у JS. У v4 файл конфіга не потрібен взагалі: ти відкриваєш свій globals.css, підключаєш Tailwind однією стрічкою і описуєш токени в блоці @theme.
@import "tailwindcss";
@theme {
--color-brand: oklch(0.87 0.24 130);
--color-surface: oklch(0.16 0.02 250);
--spacing-gutter: 1.5rem;
--radius-card: 12px;
--font-display: "Montserrat", sans-serif;
}
З цих п'яти стрічок Tailwind автоматично зробить утиліти: bg-brand, text-brand, bg-surface, p-gutter, rounded-card, font-display. Ти не пишеш жодного правила вручну — токен став утилітою.
Ключова деталь: токен = CSS-змінна
Найважливіше, що варто зрозуміти: усе всередині @theme — це звичайні нативні CSS custom properties. Tailwind не просто генерує класи, він ще й публікує ці змінні в :root. Тобто після компіляції у браузері справді існує --color-brand, і до нього має доступ будь-хто: утиліти Tailwind, твій власний CSS, сторонні бібліотеки, навіть інлайн-стилі.
Це знімає стару біль Tailwind v3, де токени сиділи в JS і були недоступні поза класами. Тепер, якщо тобі треба нестандартне значення, ти пишеш color: var(--color-brand) — і воно завжди синхронне з утилітами, бо це буквально те саме джерело.
Namespace-и: чому імена токенів мають значення
Tailwind v4 читає не будь-які змінні, а ті, що починаються з відомих префіксів-namespace. Саме префікс каже фреймворку, які утиліти згенерувати:
--color-*→ утиліти кольору:bg-*,text-*,border-*,fill-*--spacing-*→ відступи:p-*,m-*,gap-*,w-*--font-*→ сімейства шрифтів:font-*--text-*→ розміри тексту:text-sm,text-lg--radius-*→ заокруглення:rounded-*--shadow-*,--breakpoint-*,--ease-*→ тіні, брейкпоінти, криві анімації
Це фактично контракт іменування, який замінює хаос довільних назв. Той самий принцип трьох рівнів (примітив → семантика → компонент), про який ми писали в матеріалах про архітектуру токенів, лягає сюди природно: примітиви типу --color-lime-500 посилаєш у семантичні --color-brand, а їх — у контекст компонента.
Ланцюг Figma → @theme → код
Практична цінність v4 у тому, що весь шлях від змінної в Figma до класу в React стає прямим і без ручного дублювання:
- Figma Variables. Описуєш кольори, spacing і радіуси як змінні, бажано в OKLCH — він передбачувано працює з контрастом і темною темою.
- Експорт у токени. Плагін (Tokens Studio, нативний експорт змінних або MCP-міст) віддає JSON у форматі W3C DTCG.
- Генерація
@theme. Style Dictionary або невеликий скрипт перетворює JSON у стрічки--color-*,--spacing-*усередині блоку@theme. - Код. Розробник пише
bg-brand rounded-card p-gutter— і ніколи не задає значення напряму.
Змінив бренд-колір у Figma → перегенерував токени → усі компоненти оновились одночасно. Жодного пошуку хардкоду по проєкту.
Темна тема без дублювання утиліт
Оскільки токени — це CSS-змінні, темна тема робиться перевизначенням значень, а не переписуванням класів. Клас bg-surface лишається той самий; змінюється лише те, на що дивиться --color-surface:
@theme {
--color-surface: oklch(0.98 0 0);
}
@media (prefers-color-scheme: dark) {
:root { --color-surface: oklch(0.16 0.02 250); }
}
Або через [data-theme="dark"], якщо потрібен ручний перемикач. Компоненти нічого про це не знають — вони тримаються за роль, а не за конкретний колір. Це та сама логіка «двох колекцій режимів», яку дизайнери роблять у Figma Variables, тільки виражена мовою CSS.
Чому саме v4 виграє в епоху AI-кодингу
Є неочевидна, але важлива перевага. Коли ти генеруєш UI через Claude, Cursor чи інший AI-інструмент, модель значно надійніше працює з CSS, ніж із JS-конфігом. Нативні CSS custom properties — це стандарт, який модель «бачить» прямо в стилях сторінки; JavaScript-об'єкт theme.extend.colors вона мусить домислювати й часто плутає.
Тому проєкт на Tailwind v4 із чистим @theme дає AI набагато точніший контекст: він читає реальні токени, використовує правильні утиліти bg-brand замість вгадування bg-[#A8FF57], і не ламає дизайн-систему. Для «vibe coding» дизайнера це різниця між компонентом, що лягає в систему, і компонентом, який доводиться переробляти. Ми показуємо цей повний цикл — від Figma-змінних до задеплоєного React — у розборах на YouTube-каналі UX Hero.
Три помилки на старті
- Ігнорувати namespace. Змінна
--brand-colorне згенерує нічого — Tailwind чекає--color-brand. Префікс не косметика, а тригер. - Тягнути
tailwind.config.jsзі старого проєкту. У v4 він не потрібен; мікс двох підходів дає плутанину, де живе правда. Обери CSS. - Хардкодити значення «на швидку».
bg-[#A8FF57]технічно працює, але це вихід із системи. Кожен такий клас — майбутній борг при ребрендингу.
Tailwind v4 не додав нову модну фічу — він прибрав прошарок між дизайном і кодом. Токени тепер живуть в одному місці, читаються браузером, людиною і AI однаково. Для дизайнера, що йде в код, це найпростіший спосіб зробити свою дизайн-систему справжнім джерелом правди, а не документом, який ніхто не синхронізує.