ДокументацияCSSСпецифичность селекторов
Средний 8 мин чтения

Специфичность селекторов

Специфичность определяет, какой CSS-правило применится при конфликте стилей. Понимание специфичности помогает избежать !important.

specificityselectorscascadecss

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

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

p { color: black; }          /* Специфичность: 0-0-1 */
.text { color: blue; }       /* Специфичность: 0-1-0 */
#main p { color: red; }      /* Специфичность: 1-0-1 */
<p id="main" class="text">Какого цвета текст?</p>
<!-- Ответ: красного — выигрывает #main p -->

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

Специфичность записывается как три числа A-B-C:

КатегорияЗначение AПример
ID+1-0-0#header
Класс, атрибут, псевдокласс+0-1-0.btn, [type], :hover
Тег, псевдоэлемент+0-0-1div, ::before
* универсальный0-0-0*
div                    /* 0-0-1 */
.btn                   /* 0-1-0 */
#app                   /* 1-0-0 */
div.btn                /* 0-1-1 */
#app .btn              /* 1-1-0 */
#app .list > .item     /* 1-2-0 */
button:hover           /* 0-1-1 */
input[type="text"]     /* 0-1-1 */
::before               /* 0-0-1 */

Сравнение идёт слева направо: 1-0-0 всегда больше 0-99-99.

Инлайн-стили и !important

<!-- Инлайн-стили имеют специфичность 1-0-0-0 (выше ID) -->
<p style="color: green;">Текст</p>
/* !important побеждает всё, включая инлайн-стили */
p { color: red !important; }

Иерархия (от слабого к сильному):

  1. Браузерные стили по умолчанию
  2. Таблицы стилей автора
  3. Инлайн-стили
  4. !important

Порядок источников

При одинаковой специфичности побеждает последнее объявление:

.btn { color: blue; }
.btn { color: red; }  /* Это правило применится */
/* Порядок подключения стилей важен */
@import 'reset.css';
@import 'components.css'; /* Переопределяет reset.css при равной специфичности */

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

1. Держите специфичность низкой

/* Плохо — высокая специфичность */
#sidebar .nav-list li a.active { color: violet; }

/* Лучше — добавить класс прямо на элемент */
.nav-link-active { color: violet; }

2. Избегайте !important

/* !important создаёт «долг специфичности» */
.title { color: red !important; }

/* Потом придётся бороться: */
.header .title { color: blue !important; } /* Перебить не получится без ещё одного !important */

Исключение — утилитарные классы (как Tailwind), где !important обосновано.

3. Используйте () для нулевой специфичности

/* :where() имеет специфичность 0-0-0 */
:where(.card, .panel) p { color: gray; }

/* :is() сохраняет специфичность наибольшего аргумента */
:is(#app, .container) p { color: blue; } /* 1-0-1 из-за #app */

4. Слои (@layer)

CSS-слои позволяют явно управлять порядком без !important:

@layer reset, base, components, utilities;

@layer reset {
  * { margin: 0; padding: 0; }
}

@layer components {
  .btn { background: blue; } /* Переопределяет reset */
}

@layer utilities {
  .hidden { display: none; } /* Переопределяет всё выше */
}

Отладка специфичности

В DevTools браузера зачёркнутые правила — это переопределённые стили. Наведите на селектор — увидите его специфичность в tooltip.

Инструменты для расчёта: specificity.keegan.st