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

Подходы и их цена

Главных подходов три, и у каждого своя цена.

CSS Modules — обычный CSS с локальными именами классов (импортируется в компонент, классы не текут наружу). Просто, без рантайма, близко к стандарту; минус — переключение между файлом стилей и компонентом.

import styles from "./ProductCard.module.css";
export function ProductCard() {
  return <article className={styles.card}>...</article>;
}

Tailwind — утилитарные классы прямо в разметке. Быстро, согласованно по шкале значений, без переключения файлов; минус — разметка шумная, нужна привычка.

export function ProductCard() {
  return <article className="rounded-lg border p-4">...</article>;
}

CSS-in-JS — стили в JavaScript, динамика на props; минус — рантайм-цена (часть библиотек считает стили в браузере) и сложность с серверным рендером. В новых проектах его берут осторожнее, чем раньше.

Универсального лучшего нет: CSS Modules и Tailwind — безопасный выбор по умолчанию; CSS-in-JS — когда нужна сильная динамика стилей и команда готова к его цене.

Дизайн-токены

Что бы ни выбрали для механики, согласованность даёт единый источник значений — дизайн-токены: цвета, отступы, радиусы, типографика, объявленные в одном месте (часто CSS-переменными) и используемые везде.

:root {
  --color-accent: #2f5b4f;
  --space-2: 0.5rem;
  --radius: 8px;
}
.card { padding: var(--space-2); border-radius: var(--radius); }

Токены — это контракт дизайна: поменял значение в одном месте — изменилось везде, и ничего не разъезжается. Tailwind задаёт их в конфиге, CSS Modules — переменными, CSS-in-JS — темой; механизм разный, принцип один. Захардкоженные #2f5b4f и 13px по компонентам — тот же запах, что магические числа в backend-коде.

Согласованность компонентов

Дизайн-токены плюс набор общих UI-примитивов (shared/ui: Button, Input, Card) дают согласованность: новый экран собирается из тех же кирпичей с теми же значениями, а не стилизуется заново. Это превращает «каждый экран по-своему» в «весь продукт в одном языке».

Где это в UCP

Стилизация — это инженерное решение про согласованность и цену, а не украшательство: выбрать подход с понятными издержками, вынести значения в токены, собирать интерфейс из общих примитивов. Дисциплина та же, что «единый источник истины» и «не повторяйся» в backend-коде. Для продукт-инженера согласованный интерфейс — часть качества продукта, которую он держит сам; а чтобы этот интерфейс был доступен всем, нужна доступность.