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

Определение
-----------

**Специфичность** - это способ, с помощью которого браузеры определяют, какие значения свойств 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` непосредственно соответствует элементу, а стиль, задающий зелёный цвет, всего лишь унаследован от родителя.

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

* Калькулятор специфичности: Интерактивный сайт, помогающий вам проверить и понять ваши собственные правила CSS - https://specificity.keegan.st/
* Специфичность селекторов в CSS3 - http://www.w3.org/TR/selectors/#specificity
* Ключевые концепции CSS
    + Синтаксис CSS
    + @-правила
    + комментарии
    + специфичность
    + наследование
    + блочная модель
    + режимы компоновки
    + модели визуального форматирования
    + Схлопывание отступов
    + Значения
        - начальные
        - вычисленные
        - используемые
        - действительные
    + Синтаксис определения значений (en-US)
    + Сокращённые свойства
    + Замещаемые элементы