Как организовать CSS в современных веб-проектах
CSS легко писать, но сложно поддерживать. Несколько сотен строк кажутся управляемыми, пока спустя шесть месяцев вы не начинаете бояться что-либо менять, потому что не знаете, что сломается. Проблема не в самом CSS — проблема в отсутствии структуры.
Вот практический подход к организации CSS, который масштабируется, остается читаемым и работает с современными инструментами.
Ключевые выводы
- Используйте нативные каскадные слои CSS (
@layer) для контроля порядка стилей и устранения конфликтов специфичности. - Структурируйте дизайн-токены в иерархии от примитивов к семантике, чтобы изменение темы требовало правок в одном месте, а не в десятках.
- Размещайте стили компонентов рядом с самими компонентами, используя CSS Modules или аналогичные инструменты изоляции.
- Держите вложенность неглубокой — два уровня обычно являются пределом, после которого проблемы специфичности возвращаются.
- Используйте четкую файловую структуру, которая разделяет глобальные стили от стилей компонентов без непреднамеренного смешивания.
Начните с четкой структуры слоев
Самое важное решение в архитектуре CSS — это контроль того, где находятся стили и в каком порядке они применяются. Нативные каскадные слои CSS (@layer) делают это явным.
@layer reset, tokens, base, components, utilities;
Объявление слоев заранее означает, что более поздние слои побеждают более ранние — независимо от специфичности. Больше никакой борьбы с каскадом через всё более специфичные селекторы или хаки с !important.
Практичный порядок слоев:
- reset — нормализация браузерных стилей по умолчанию
- tokens — пользовательские CSS-свойства (ваши дизайн-токены)
- base — стили на уровне элементов (
body,h1,a) - components — изолированные стили UI
- utilities — однозначные переопределения
Эта структура дает вам предсказуемую специфичность и четкую ментальную модель того, где должен находиться любой конкретный стиль.
Дизайн-токены принадлежат основе
Дизайн-токены — это именованные значения для цветов, отступов, типографики и других дизайн-решений. Определенные как пользовательские CSS-свойства, они создают единый источник истины во всей вашей кодовой базе.
:root {
--color-primary: oklch(55% 0.2 250);
--space-md: 1rem;
--font-body: "Inter", sans-serif;
}
Организуйте токены от примитивов к семантике:
- Примитивы:
--blue-500: oklch(55% 0.2 250) - Семантика:
--color-action: var(--blue-500) - Компонент:
--btn-bg: var(--color-action)
Эта иерархия означает, что вы можете изменить тему всего проекта, меняя семантические токены, а не охотясь по стилям компонентов.
Компонентная стилизация: изолируйте свои стили
Глобальные таблицы стилей обрабатывают базовые стили. Компоненты обрабатывают всё остальное. Ключевой принцип: размещайте стили рядом с компонентом, к которому они относятся.
CSS Modules — самый простой способ достичь этого в React, Vue или любом проекте на основе сборщика. Каждый файл .module.css по умолчанию локально изолирован — имена классов преобразуются в уникальные идентификаторы во время сборки, поэтому .button в одном компоненте никогда не конфликтует с .button в другом.
/* Button.module.css */
.button {
background: var(--btn-bg);
padding: var(--space-sm) var(--space-md);
}
Нативная вложенность CSS (теперь поддерживается во всех современных браузерах) также снижает потребность в препроцессорах в стилях компонентов:
.card {
padding: var(--space-md);
& .card-title {
font-size: 1.25rem;
}
}
Держите вложенность неглубокой — двух уровней обычно достаточно. Глубокая вложенность воссоздает проблемы специфичности, которых вы пытались избежать.
Нативный @scope теперь широко доступен, но в прикладном коде он всё еще менее распространен, чем CSS Modules или изоляция на уровне фреймворка, поэтому рассматривайте его как развивающуюся опцию, а не как вариант по умолчанию.
Discover how at OpenReplay.com.
Утилитарный CSS: где находится Tailwind v4
Tailwind CSS v4 использует другой подход: вместо написания CSS компонентов вы компонуете стили непосредственно в разметке, используя утилитарные классы. Версия 4 переходит на модель конфигурации, основанную на CSS — вы настраиваете Tailwind внутри CSS-файла с помощью @theme, а не в JavaScript-конфиге.
@import "tailwindcss";
@theme {
--color-primary: oklch(55% 0.2 250);
}
Tailwind хорошо работает для команд, которым нужна быстрая итерация и последовательные дизайн-ограничения. Компромисс — многословная разметка и менее семантичные имена классов. Многие команды используют гибридный подход: утилиты Tailwind для раскладки и отступов, CSS Modules или пользовательские свойства для сложной логики компонентов.
Практичная файловая структура
Для большинства проектов эта структура хорошо масштабируется:
styles/
index.css ← только импорты, объявляет порядок @layer
tokens.css ← дизайн-токены
reset.css ← нормализация браузера
base.css ← стили элементов
utilities.css ← вспомогательные классы
components/
Button/
Button.jsx
Button.module.css
Глобальные стили находятся в styles/. Стили компонентов находятся рядом с компонентом. Ничто не просачивается через эту границу без веской причины.
Заключение
Хорошая организация CSS сводится к нескольким последовательным привычкам: объявляйте порядок слоев заранее, определяйте дизайн-токены в корне, изолируйте стили компонентов локально и держите селекторы неглубокими. Вам не нужна жесткая методология — вам нужны четкие соглашения, которые понимает и соблюдает вся ваша команда.
Начинайте просто. Добавляйте структуру только тогда, когда проект этого требует.
Часто задаваемые вопросы
Да. Tailwind v4 построен на основе нативных каскадных слоев (theme, base, components, utilities). Вместо того чтобы оборачивать его вывод, вы контролируете каскад, размещая свой собственный CSS в соответствующем слое, чтобы он предсказуемо компоновался с утилитами Tailwind.
Они решают разные проблемы. Вложенность CSS уменьшает многословность и группирует связанные правила, но не изолирует имена классов. CSS Modules гарантируют локальную изоляцию, генерируя уникальные идентификаторы во время сборки. Для проектов, где несколько компонентов могут использовать одинаковые имена классов, такие как button или title, CSS Modules остаются более надежным механизмом изоляции.
Каждый дизайн-токен является пользовательским CSS-свойством, но не каждое пользовательское свойство является дизайн-токеном. Дизайн-токены представляют собой продуманные дизайн-решения, такие как фирменные цвета, шкалы отступов и размеры шрифтов. Они организованы в иерархии от примитивов к семантике, так что изменение одного семантического токена может изменить тему всего проекта без редактирования отдельных стилей компонентов.
Утилитарный CSS, такой как Tailwind, лучше всего работает для быстрого прототипирования и команд, которые предпочитают размещать стилевые решения в разметке. Компонентно-изолированный CSS подходит для проектов со сложной UI-логикой или строгим разделением ответственности. Многие команды комбинируют оба подхода, используя утилиты для раскладки и отступов, оставляя изолированные таблицы стилей для компонентов с состоянием или сильно кастомизированных компонентов.
Truly understand users experience
See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..