Урок 01. Теория: утилитарный подход

📁 Раздел: Введение ⏱️ Время изучения: ~40 мин 🎯 Сложность: Начальная

⚡ Кратко

Утилита — класс на одно свойство: p-4 это padding: 1rem, flex это display: flex. Интерфейс собирается композицией утилит прямо в разметке, поэтому исчезает задача «придумать имя классу» и вместе с ней — растущий, никем не удаляемый CSS-файл. Значения берутся из фиксированной шкалы, поэтому отступы и размеры в проекте сами собой остаются согласованными. Плата за это — длинные строки классов в HTML.

Главная идея: класс = одно свойство

Классический CSS работает так: вы придумываете смысловое имя (.product-card), а затем в отдельном файле описываете, как этот смысл выглядит. Tailwind предлагает обратный подход: классы описывают не смысл, а оформление, и каждый отвечает ровно за одно свойство.

/* обычный CSS: имя описывает смысл */
.product-card { padding: 1.25rem; border-radius: 0.75rem; }
<!-- Tailwind: классы описывают оформление -->
<div class="p-5 rounded-xl">…</div>

Один класс — одно решение. p-5 всегда означает padding: 1.25rem, где бы он ни встретился: он не зависит от каскада, от порядка подключения файлов и от того, что написал коллега в соседнем компоненте.

Обычный CSS — это заказать у столяра готовый шкаф: красиво, но каждый новый шкаф — новый заказ, а старые продолжают занимать место на складе, даже когда ими никто не пользуется. Tailwind — это система полок из типовых деталей: деталей мало, они одинаковой длины, и собрать из них можно что угодно. Ненужную конструкцию просто разбираешь — «складом» она не становится.

Какую боль это лечит

Проблемы, из-за которых утилитарный подход вообще появился, знакомы каждому, кто вёл CSS-проект дольше пары месяцев:

  • Именование. Полчаса споров, как назвать блок: .card-inner, .card__body или .card-content. В утилитарном подходе такого решения просто нет.
  • Файл только растёт. Удалить правило страшно: неизвестно, кто им пользуется. CSS накапливается годами, и половина его мертва.
  • Каскадные сюрпризы. Кто-то поднял специфичность селектора — и ваш компонент выглядит иначе на одной из страниц.
  • Рассогласованные значения. В одном месте отступ 18px, в другом 20px, в третьем 1.2rem — потому что каждый писал «на глаз».

Утилиты убирают первые три пункта конструктивно, а четвёртый — за счёт шкалы: p-4 и p-5 есть, а «18 пикселей на глаз» нужно писать отдельным, заметным в ревью синтаксисом p-[18px].

Как это выглядит на практике

Ниже — обычная карточка. Никакого CSS-файла к ней не прилагается: всё оформление в атрибуте class.

Отчёт готов

Данные за июль обновлены пять минут назад.

<div class="max-w-sm rounded-xl border border-slate-200 bg-white p-5 shadow-sm">
  <h3 class="text-base font-semibold text-slate-900">Отчёт готов</h3>
  <p class="mt-1 text-sm text-slate-600">Данные за июль обновлены пять минут назад.</p>
  <button class="mt-4 rounded-md bg-slate-900 px-3 py-2 text-sm font-medium text-white hover:bg-slate-700">
    Открыть
  </button>
</div>

Прочитайте классы как список свойств: ширина не больше max-w-sm, скругление rounded-xl, рамка border border-slate-200, фон bg-white, внутренний отступ p-5, лёгкая тень shadow-sm. Это буквальный перевод дизайн-макета в разметку.

Откуда берётся маленький CSS

Tailwind не отдаёт браузеру «все возможные классы». Сборщик сканирует ваши файлы, находит в них строки, похожие на имена утилит, и генерирует CSS только для найденных. Не использовали rotate-45 — его не будет в итоговом файле. Поэтому размер CSS зависит от разнообразия вашей вёрстки, а не от размера фреймворка, и почти не растёт по мере добавления новых страниц: новые страницы переиспользуют те же утилиты.

💡 На заметку: именно поэтому имя класса нельзя собирать из кусочков в JavaScript — сканер видит только текст файла, а не результат выполнения кода. Подробнее — в уроке 03 и в разделе «Ошибки».

Честные минусы

Подход не бесплатный, и делать вид, что минусов нет, — плохая услуга:

  • Разметка становится «шумной». Строка из пятнадцати классов читается хуже, чем class="card". Лечится компонентами (урок 15) и переносом строк.
  • Нужен инструментарий. Расширение редактора с автодополнением и сортировкой классов из желательного превращается в необходимое.
  • Порог входа в чужой код. Пока не знаешь шкалу, gap-2 ничего не говорит; через неделю — говорит больше, чем .list-spacing.
  • Дублирование разметки. Пять одинаковых кнопок — пять одинаковых строк классов. Это решается компонентом, а не копипастой.

Практическое правило: утилиты — для оформления, компоненты — для повторов. Если один и тот же набор классов встретился третий раз, пора делать компонент.

Когда утилитарный подход не нужен

  • Страница из трёх абзацев без сборки и без планов на развитие: обычного CSS хватит.
  • Проект живёт на готовом дизайн-фреймворке (например, Bootstrap) и менять его никто не собирается.
  • Письма и HTML-документы для почтовых клиентов — там свои правила и inline-стили.
Дальше: в уроке 02 поставим Tailwind в проект четырьмя разными способами и посмотрим, какой выбрать в вашем случае.