Специфичность

Определение

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

Как вычисляется специфичность?

Специфичность представляет собой вес, придаваемый конкретному правилу CSS. Вес правила определяется количеством каждого из типов селекторов в данном правиле. Если у нескольких правил специфичность одинакова, то к элементу применяется последнее по порядку правило CSS. Специфичность имеет значение только в том случае, если один элемент соответствует нескольким правилам. Согласно спецификации CSS, правило для непосредственно соответствующего элемента всегда будет иметь больший приоритет, чем правила, унаследованные от предка.

Примечание: Примечание: Взаимное расположение элементов в дереве документа не влияет на специфичность.

Типы селекторов

В следующем списке типы селекторов расположены по возрастанию специфичности:

  1. селекторы типов элементов (например, h1) и псевдоэлементов (например, ::before).
  2. селекторы классов (например, .example), селекторы атрибутов (например, [type="radio"]) и псевдоклассов (например, :hover).
  3. селекторы идентификаторов (например, #example).

Универсальный селектор (*), комбинаторы (+, >, ~, '``') и отрицающий псевдокласс (:not()) не влияют на специфичность. (Однако селекторы, объявленные внутри :not(), влияют)

Стили, объявленные в элементе (например, style="font-weight:bold"), всегда переопределяют любые правила из внешних файлов стилей и, таким образом, их специфичность можно считать наивысшей.

Важное исключение из правил - !important

Когда при объявлении стиля используется модификатор !important, это объявление получает наивысший приоритет среди всех прочих объявлений. Хотя технически модификатор !important не имеет со специфичностью ничего общего, он непосредственно на неё влияет. Поскольку !important усложняет отладку, нарушая естественное каскадирование (en-US) ваших стилей, он не приветствуется и следует избегать его использования. Если к элементу применимы два взаимоисключающих стиля с модификатором !important, то применён будет стиль с большей специфичностью.

Несколько практических советов:

  • Всегда пытайтесь использовать специфичность, а !important используйте только в крайних случаях
  • Используйте !important только в страничных стилях, которые переопределяют стили сайта или внешние стили (стили библиотек, таких как Bootstrap или normalize.css)
  • Никогда не используйте !important, если вы пишете плагин или мэшап.
  • Никогда не используйте !important в общем CSS сайта.

Вместо !important можно:

  1. Лучше использовать каскадные свойства CSS
  2. Использовать более специфичные правила. Чтобы сделать правило более специфичным и повысить его приоритет, укажите один элемент или несколько перед нужным вам элементом:
    html
    <div id="test">
      <span>Text</span>
    </div>
    
    css
    div#test span {
      color: green;
    }
    div span {
      color: blue;
    }
    span {
      color: red;
    }
    

Вне зависимости от порядка следования правил, текст всегда будет зелёным, поскольку у этого правила наибольшая специфичность (при этом, правило для голубого цвета имеет преимущество перед правилом для красного, несмотря на порядок следования).

Вам придётся использовать !important если:

А) Первый сценарий:

  1. У вас есть общий файл стилей, устанавливающий правила для внешнего вида сайта.
  2. Вы пользуетесь (или кто-то другой пользуется) весьма сомнительным средством - объявлением стилей непосредственно в элементах

В таком случае вам придётся объявить некоторые стили в вашем общем файле CSS как !important, переопределяя, таким образом, стили, установленные в самих элементах.

Пример из практики: Некоторые плохо написанные плагины jQuery, использующие присваивание стилей самим элементам.

Б) Ещё сценарий:

css
#someElement p {
  color: blue;
}

p.awesome {
  color: red;
}

Как сделать цвет текста в абзацах awesome красным всегда, даже если они расположены внутри #someElement? Без !important у первого правила специфичность больше и оно имеет преимущество перед вторым.

Как преодолеть !important:

A) Просто добавьте ещё одно правило с модификатором !important, у которого селектор имеет большую специфичность (благодаря добавлению типа элемента (тэга), идентификатора (атрибута id) или класса к селектору).

Пример большей специфичности:

css
table td {
  height: 50px !important;
}
.myTable td {
  height: 50px !important;
}
#myTable td {
  height: 50px !important;
}

Б) Или добавьте правило с модификатором !important и таким же селектором, но расположенное в файле после существующего (при прочих равных выигрывает последнее объявленное правило):

css
td {
  height: 50px !important;
}

В) Или перепишите первоначальное правило без использования !important.

С более подробной информацией можно ознакомиться по следующим ссылкам:

Когда надо использовать !important в CSS?

Что означает !important в CSS?

Когда в CSS надо использовать модификатор !important

Как преодолеть !important

Как использовать модификатор !important в CSS чтобы сэкономить время

Не исключение - :not()

Отрицающий псевдокласс :not не учитывается как псевдокласс при расчёте специфичности. Однако селекторы, расположенные внутри :not, при подсчёте количества по типам селекторов рассматриваются как обычные селекторы и учитываются.

Следующий фрагмент CSS ...

css
div.outer p {
  color: orange;
}
div:not(.outer) p {
  color: lime;
}

... применённый к такому HTML ...

html
<div class="outer">
  <p>Это div.outer</p>
  <div class="inner">
    <p>Это текст в div.inner</p>
  </div>
</div>

... отобразится на экране так:

Это div.outer

Это текст в div.inner

Специфичность основана на форме

Специфичность опирается на форму селектора. В следующем примере, при определении специфичности селектора, селектор *[id="foo"] считается селектором атрибута, даже при том, что ищет идентификатор.

Эти объявления стилей ...

css
*#foo {
  color: green;
}
*[id="foo"] {
  color: purple;
}

... применённые к нижеследующей разметке ...

html
<p id="foo">Это пример.</p>

... в результате выглядят так:

Это пример.

Потому что оба правила соответствуют одному и тому же элементу, но селектор идентификатора имеет большую специфичность.

Независимость от расположения

Взаимное расположение элементов, указанных в селекторе не влияет на специфичность правила. Следующие объявления стилей ...

css
body h1 {
  color: green;
}
html h1 {
  color: purple;
}

... в сочетании со следующим HTML ...

html
<html>
  <body>
    <h1>Вот заголовок!</h1>
  </body>
</html>

... отобразится как:

Вот заголовок!

Потому что, хотя оба объявления имеют одинаковое количество типов селекторов, но селектор html h1 объявлен последним.

Непосредственно соответствующие элементы и унаследованные стили

Стили непосредственно соответствующих элементов всегда предпочитаются унаследованным стилям, независимо от специфичности унаследованного правила. Этот CSS ...

css
#parent {
  color: green;
}
h1 {
  color: purple;
}

... с таким HTML ...

html
<html>
  <body id="parent">
    <h1>Вот заголовок!</h1>
  </body>
</html>

... тоже отобразится как:

Вот заголовок!

Потому что селектор h1 непосредственно соответствует элементу, а стиль, задающий зелёный цвет, всего лишь унаследован от родителя.

Дополнительная информация