webroad.online
  1. 1Веб
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Инструменты
  8. 8React
  9. 9Стейт-менеджмент
  10. 10Next.js
  11. 11Формы
  12. 12Данные и бэкенд
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Анимации
  16. 16Тестирование
  17. 17Архитектура
Tailwind CSS · Урок 5 из 6

Компоненты и варианты

Компоненты вместо @apply, варианты, cn/tailwind-merge, динамические классы.

Обновлено

Проблема

С Tailwind один и тот же набор классов (кнопка, карточка) встречается десятки раз. Как переиспользовать их, не копируя повсюду? Вариантов несколько — рекомендуется только один.

Вариант Пример Вердикт
копипаст те же 10 классов в 30 местах ✗ невозможно изменить
@apply в CSS .btn { @apply px-4 py-2 } ✗ заново изобретаете классический CSS и теряете преимущества
компонент <Button variant="primary"> ✓ рекомендуется
циклы / map {items.map(i => <li className="...">)} ✓ классы встречаются в коде один раз

Переиспользование = компоненты, а не @apply

/* ✗ заново изобретаете классический CSS и теряете преимущества */
.btn { @apply rounded-md px-4 py-2 bg-accent; }
// ✓ единица переиспользования — компонент
export function Button(props) {
  return <button className="rounded-md px-4 py-2 bg-accent text-white" {...props} />
}

@apply годится только для стилей, которые вы не контролируете компонентами (контент из CMS, внешние библиотеки).

Варианты — базовый паттерн

Ровно то, что делает shared/ui/button.tsx в проекте:

const variants = {
  primary: 'bg-accent text-accent-fg hover:bg-accent-hover',
  secondary: 'border border-line-strong bg-surface hover:bg-hover',
  ghost: 'text-muted hover:bg-hover',
}
const sizes = { sm: 'h-8 px-3', md: 'h-9 px-4' }

<button className={cn(base, variants[variant], sizes[size], className)} />

Варианты конечны и именованы — вы не принимаете color="#f00" как prop.

cn, clsx, tailwind-merge

  • clsx / простой cn — склеивает классы по условию.
  • tailwind-merge — разрешает конфликты: twMerge('px-2', 'px-4') → 'px-4'. Полезно, когда разрешаете внешний className, который переопределяет стили.
  • cva (class-variance-authority) / tailwind-variants — декларативный API для вариантов, полезен при большом числе комбинаций.

Динамические классы — ловушка

Tailwind находит классы, читая текст файлов. Собранные из частей классы он угадать не может:

`bg-${color}-500`                              // ✗ в итоговом CSS этого нет
const colors = { red: 'bg-red-500', blue: 'bg-blue-500' }
colors[color]                                  // ✓ полные классы, написанные буквально

Стили из динамических данных

Значения, вычисляемые во время работы → style или CSS-переменная:

<div className="w-(--progress) bg-success" style={{ '--progress': `${pct}%` }} />

Коротко

  • Единица переиспользования — компонент, а не @apply.
  • Конечные именованные варианты в объекте; cn для склейки, tailwind-merge для конфликтов.
  • Классы нужно писать в коде целиком — Tailwind не видит классы, собранные из частей.

Официальные источники

Упражнения

Была ли страница полезной?

Один клик — без регистрации.