Каскад и специфичность: почему одни стили побеждают другие (CSS)

В CSS есть чёткие правила, по которым браузер решает, какое правило применить. Это и есть каскад плюс специфичность.


Что такое каскад

Каскад — это просто «порядок сверху вниз». Если у двух правил одинаковая сила (одинаковая специфичность), победит то, которое написано ниже в коде.

Пример:

css
p { color: blue; }
p { color: red; }

У обоих правил селектор одинаковый (p), специфичность равна. Работает каскад: второе правило ниже → цвет текста будет красный.

Это самое простое правило: при равной силе побеждает последний.


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

Специфичность — это «вес» селектора. Браузер не просто смотрит, кто ниже, а сначала проверяет, у кого селектор «сильнее».

Грубый подсчёт «веса» (для понимания, без формул):

  • селектор по тегу (p, div) — слабый;
  • селектор по классу (.card, .btn) — средний;
  • селектор по ID (#main) — сильный;
  • inline‑стили (style="...") — очень сильный.

Если у одного правила вес больше, оно победит даже если написано выше.

Пример 1: класс сильнее тега

css
p { color: blue; }        /* тег — слабый */
.special { color: red; }  /* класс — сильнее */
html
<p class="special">Текст</p>

Цвет будет красный, несмотря на то, что правило с p стоит первым. Класс «тяжелее» тега.


Пример 2: ID сильнее класса

css
.special { color: red; }     /* класс */
#main p { color: green; }    /* ID + тег → ещё сильнее */
html
<div class="content">
  <p>Текст</p>
</div>

Цвет будет зелёный. Селектор #main p имеет ID, поэтому он побеждает класс .special.


Пример 3: комбинация селекторов увеличивает вес

css
div p { color: orange; }       /* тег + тег */
.content p { color: purple; }  /* класс + тег → тяжелее */
html
<div class="content">
  <p>Текст</p>
</div>

Цвет фиолетовый. .content p сильнее, чем div p, потому что класс добавляет вес.

Чем больше «кусочков» в селекторе (классы, ID, вложенность), тем он тяжелее. Но не стоит специально делать селекторы «очень тяжёлыми» ради победы — потом их сложно переопределить.


Порядок, в котором браузер всё сравнивает

Когда стилей много, браузер действует по шагам:

  1. Происхождение и важность. Сначала смотрит, нет ли правила с !important. Если есть — оно почти всегда побеждает (но злоупотреблять им не надо). Также учитывает стили браузера, пользовательские стили и т.п.
  2. Специфичность. Если !important нет, сравнивает «вес» селекторов. Побеждает более специфичный.
  3. Каскад (порядок в коде). Если специфичность одинаковая, побеждает правило, которое написано ниже.

Частый кейс: почему твой стиль не работает

Ты пишешь:

css
.btn { background: red; }

А кнопка остаётся синей. Скорее всего, где‑то есть правило вроде:

css
#header .btn { background: blue; }

Селектор #header .btn содержит ID, он тяжелее, чем просто .btn. Поэтому синий цвет побеждает.

Как исправить без «наращивания веса»:

  • Переместить своё правило ниже (если специфичность такая же).
  • Сделать селектор чуть точнее, но не слишком тяжёлым. Например: .page-buttons .btn { background: red; }, если это логично по структуре.
  • Не ставить ID на каждый элемент и не делать цепочки вида #main #content .box .item — такие селекторы потом почти невозможно переопределить без !important.

Пример с inline‑стилями

css
.text { color: green; }
html
<p class="text" style="color: orange;">Текст</p>

Цвет будет оранжевый. style="..." — это почти самый сильный вариант. Он перебивает обычные классы и теги.

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


Шпаргалка по приоритету (от самого сильного к слабому)

  1. Стили с !important (если они из того же источника).
  2. Inline‑стили (style="...").
  3. Селекторы с ID.
  4. Селекторы с классами, атрибутами, псевдоклассами.
  5. Селекторы по тегам и псевдоэлементам.
  6. Универсальный селектор * (почти без веса).

И при равном весе побеждает то, что написано ниже.


Ещё один пример целиком

CSS:

css
p { color: blue; }           /* 1 */
.text { color: red; }        /* 2 */
#content p { color: green; }  /* 3 */

HTML:

html
<div id="content">
  <p class="text">Текст</p>
</div>

Какой цвет? Зелёный. У #content p есть ID — он самый специфичный, поэтому побеждает и тег, и класс, даже если они написаны ниже.


Практический совет

  • Держи специфичность низкой и ровной. Лучше .card и .card-highlight, чем #main .wrapper .content .card.
  • Если стиль «не применяется», сначала проверь:
    • нет ли более специфичного селектора выше или ниже;
    • не перебивает ли его inline‑стиль;
    • не стоит ли где‑то !important;
    • правильно ли написан селектор (точка для класса, решётка для ID).

Добавить комментарий