Каскад и приоритеты CSS: как браузер выбирает итоговый стиль

CSS / Основы

Каскад и приоритеты CSS: как браузер выбирает итоговый стиль

Пошагово разбираем каскад, происхождение правил, cascade layers, специфичность, порядок и наследование без злоупотребления !important.

Опубликовано 04.09.2026 4 минуты чтения
Содержание статьи

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

Простой конфликт

HTML
<p class="message">Сборка завершена</p>​

CSS
p {  color: #344054;}​.message {  color: #067647;}​

Оба правила подходят, но класс имеет большую специфичность, поэтому текст будет зелёным.

Если селекторы равны по приоритету, побеждает объявление, расположенное позже:

CSS
.message {  color: green;}​.message {  color: purple;}​

Итоговый цвет — purple.

Порядок решений каскада

Упрощённо браузер проходит этапы:

  1. Релевантность. Подходит ли селектор и выполняется ли условие @media?
  2. Происхождение и важность. Сравниваются стили браузера, пользователя и автора, обычные и !important, а также переходы и анимации.
  3. Cascade layers. Для правил одного происхождения учитывается порядок слоёв.
  4. Специфичность. Сравнивается вес селекторов внутри одного уровня.
  5. Близость области @scope. Если используются scoped-правила, выигрывает ближайшая граница.
  6. Порядок объявления. При полном равенстве побеждает более позднее правило.

Специфичность не может «перепрыгнуть» более важное происхождение или слой.

Как считать специфичность

Для практики удобно представить три группы:

  1. идентификаторы #id;
  2. классы, атрибуты и псевдоклассы;
  3. теги и псевдоэлементы.
CSS
#app .card p        /* 1-1-1 */.card[data-state] p /* 0-2-1 */.card__text         /* 0-1-0 */​

Сначала сравнивается количество идентификаторов, затем классов, затем типов. Большое число тегов не перевесит один класс.

Inline-стиль имеет отдельный высокий приоритет среди обычных авторских объявлений:

HTML
<p style="color: tomato">...</p>​

Поэтому inline-стили усложняют переопределение и редко подходят для обычной дизайн-системы.

Особые псевдоклассы

:where() всегда имеет нулевую специфичность:

CSS
:where(.article) h2 {  margin-block-start: 2em;}​

Такое базовое правило легко переопределить классом компонента.

:is(), :not() и :has() сами не добавляют вес, но принимают специфичность наиболее сильного селектора в списке:

CSS
.card:has(.card__image) {  grid-template-rows: auto 1fr;}​

Не прячьте внутри :is() идентификатор без необходимости: он повысит вес всего селектора.

Cascade layers

Слои позволяют заранее определить порядок групп стилей:

CSS
@layer reset, base, components, utilities;​@layer base {  a {    color: #4f46e5;  }}​@layer components {  .button {    color: #ffffff;  }}​

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

У !important порядок слоёв разворачивается: ранние важные слои получают преимущество. Это защищает базовые ограничения, но делает модель сложнее — используйте важные объявления редко.

!important

CSS
.button {  color: white !important;}​

!important меняет уровень каскада, а не просто добавляет специфичность. Ответное !important запускает новый конфликт и быстро превращает стили в гонку.

Сначала попробуйте:

  • снизить специфичность базового правила через :where();
  • выстроить порядок слоёв;
  • удалить лишние селекторы и идентификаторы;
  • поставить вариацию компонента после базы;
  • исправить владельца визуального контракта.

!important может быть оправдан для редкой utility-гарантии или пользовательского override, но решение должно быть осознанным.

Наследование — не каскад между подходящими правилами

Некоторые свойства, например color и font-family, наследуются от родителя, если у элемента нет собственного каскадного значения.

CSS
.card {  color: #20242c;}​.card__link {  color: inherit;}​

margin, padding, border обычно не наследуются. Ключевые слова:

  • inherit — взять вычисленное значение родителя;
  • initial — использовать начальное значение свойства;
  • unset — наследовать для наследуемого свойства, иначе взять начальное;
  • revert — откатить текущий уровень каскада;
  • revert-layer — откатить объявления текущего слоя.

Как отлаживать конфликт

  1. Выберите элемент в DevTools.
  2. Найдите свойство в панели Styles или Computed.
  3. Посмотрите, какие объявления зачёркнуты.
  4. Проверьте @media, слой и наличие !important.
  5. Сравните специфичность только после предыдущих уровней.
  6. Исправьте структуру правил, а не добавляйте случайный более длинный селектор.

Что запомнить

Каскад — это упорядоченный алгоритм, а специфичность — только один его этап. Проектируйте низкую специфичность, понятные слои и локальные классы компонентов. DevTools почти всегда быстрее объясняет конфликт, чем очередной !important.

Сообщить об ошибке в статье

Рекомендации редакции

Другие публикации из этого раздела.

Новые материалы

Получайте практические разборы без информационного шума

Одна общая рассылка о новых статьях и инструментах. Адрес будет активироваться только после подтверждения.

Подписка появится после подключения сервиса рассылок и Yandex SmartCaptcha.