Специфика

Подкаст CSS - 003: Специфичность

Предположим, что вы работаете со следующим HTML и CSS:

<button class="branding">Hello, Specificity!</button>
.branding {
  color: blue;
}

button {
  color: red;
}

Здесь есть два правила, которые нацелены на один и тот же элемент. Каждое правило содержит объявление, которое хочет задать цвет кнопки: одно пытается окрасить кнопку в красный цвет, а другое пытается окрасить ее в синий цвет. Какое объявление применяется к элементу?

Понимание алгоритма специфичности CSS является ключом к пониманию того, как CSS выбирает между конкурирующими объявлениями.

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

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

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

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

Специфичность — это не десятичное число, а триада, состоящая из трех компонентов: A , B и C

  • A : специфичность, подобная идентификатору
  • B : специфичность класса
  • C : специфичность, подобная элементу

Часто его представляют с помощью нотации (A,B,C) . Например: (1,0,2) . Также часто используется альтернативная нотация ABC .

Диаграмма, показывающая три компонента специфичности (A,B,C). Для каждого компонента диаграмма показывает, что он представляет, и некоторые примеры селекторов, которые на него влияют.
Диаграмма, демонстрирующая, на какой компонент специфичности влияют различные селекторы.

Как сравнивать специфику

Специфичность сравнивается путем сравнения трех компонентов по порядку: специфичность с большим значением A является более специфичной; если два значения A равны, то специфичность с большим значением B является более специфичной; если два значения B также равны, то специфичность с большим значением C является более специфичной; если все значения равны, то две специфичности равны.

Например, (1,0,0) считается более высокой специфичностью, чем (0,4,3) поскольку значение A в (1,0,0) (которое равно 1 ) больше значения A в (0,4,3) (которое равно 0 ).

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

Каждая часть в триаде специфичности начинается со значения 0 , поэтому специфичность по умолчанию равна (0,0,0) . Каждая часть селектора увеличивает специфичность, которая, в зависимости от типа селектора, увеличивает значение A , B , или C .

Универсальный селектор

Универсальный селектор ( * ) не добавляет никакой специфичности , оставляя свое значение на уровне начальной специфичности (0,0,0) .

* {
  color: red;
}

Селектор элемента или псевдоэлемента

Селектор элемента (типа) или псевдоэлемента добавляет специфичность, подобную элементу , которая увеличивает компонент C на 1 .

Следующие примеры имеют общую специфичность (0,0,1) .

Селектор типа

div {
  color: red;
}

Селектор псевдоэлементов

::selection {
  color: red;
}

Селектор класса, псевдокласса или атрибута

Селектор класса , псевдокласса или атрибута добавляет специфичность, подобную классу, которая увеличивает компонент B на 1 .

Следующие примеры имеют специфичность (0,1,0) .

Селектор класса

.my-class {
  color: red;
}

Селектор псевдокласса

:hover {
  color: red;
}

Селектор атрибутов

[href='#'] {
  color: red;
}

Селектор идентификатора

Селектор идентификатора добавляет специфичность, подобную идентификатору , которая увеличивает компонент A на 1, если вы используете селектор идентификатора ( #myID ), а не селектор атрибута ( [id="myID"] ).

В следующем примере специфичность равна (1,0,0)

#myID {
  color: red;
}

Другие селекторы

В CSS много селекторов. Не все из них добавляют специфичность. Например, сам псевдокласс :not() ничего не добавляет к расчету специфичности.

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

div:not(.my-class) {
  color: red;
}

Псевдокласс [:is()](https://developer.mozilla.org/en-US/docs/Web/CSS/:is) также сам по себе не добавляется к вычислению специфичности. Как и :not() , он берет специфичность своего наиболее специфичного аргумента.

:is(h1, h2, h3) {
  color: blue;
}

Этот образец имеет специфичность (0,0,1) поскольку он имеет только один вид селектора ( type ).

При добавлении id специфичность увеличивается до (1,0,0) .

:is(h1, h2, h3, #my-heading) {
  color: blue;
}

Псевдокласс [:where()](https://developer.mozilla.org/docs/Web/CSS/:where) отличается. Независимо от специфичности любого из его аргументов, он всегда имеет специфичность (0,0,0) .

:where(h1, h2, h3, #my-heading) {
  color: blue;
}

Низкоспецифичные стили, применяемые с помощью :where() позволяют вам переопределять эти стили с помощью базовых селекторов позже в вашей таблице стилей:

:where(#my-content) {
   color: red;
}

p {
   color: blue;
}

Несмотря на то, что :where() имеет id в списке аргументов, он по-прежнему имеет специфичность только (0, 0, 0) , поэтому базовый селектор p переопределяет его, и текст будет blue .

Проверьте свое понимание

Проверьте свои знания по оценке специфичности

Какова специфика a[href="#"] ?

(0,0,1)
Значение a равно (0,0,1) , а значение [href="#"] равно (0,1,0) .
(0,1,0)
Попробуйте еще раз! Символ a имеет значение (0,0,1) , а [href="#"] имеет значение (0,1,0) .
(0,1,1)
Значение a равно (0,0,1) , а значение [href="#"] равно (0,1,0) , что обеспечивает общую специфичность (0,1,1) .

Факторы, не влияющие на специфичность

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

Атрибуты встроенного стиля

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

<div style="color: red"></div>

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

Например, вы можете добавить к нему !important , чтобы он стал частью источника Authored !important .

!important заявления

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

В следующем примере специфичность .my-class не имеет значения для победы объявления !important .

.my-class {
  color: red !important;
  color: white;
}

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

.branding {
  color: blue !important;
}

button {
  color: red !important;
}

Конкретность в контексте

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

<a class="my-class another-class" href="#">A link</a>

Эта ссылка имеет два класса. Правило в следующем CSS имеет специфичность (0,0,1) :

a {
  color: red;
}

Если вы ссылаетесь на один из классов в селекторе, то теперь он имеет специфичность (0,1,1) :

a.my-class {
  color: green;
}

Добавьте другой класс к селектору, теперь он имеет специфичность (0,2,1) :

a.my-class.another-class {
  color: rebeccapurple;
}

Добавьте атрибут href к селектору, теперь он имеет специфичность (0,3,1) :

a.my-class.another-class[href] {
  color: goldenrod;
}

Наконец, добавьте ко всему этому псевдокласс :hover , и селектор получит специфичность (0,4,1) :

a.my-class.another-class[href]:hover {
  color: lightgrey;
}

Проверьте свое понимание

Проверьте свои знания по оценке специфичности

Какой из следующих селекторов имеет специфичность (0,2,1) ?

article > section
Элементы добавляют специфичность, подобную элементу (компонент `C`). В селекторе 2 элемента, что делает его специфичным (0,0,2) .
article.card.dark
Элементы добавляют специфичность, подобную элементу (компонент `C`), а классы добавляют специфичность, подобную классу (компонент `B`). С 2 классами и 1 элементом это делает этот селектор имеющим специфичность (0,2,1) .
article:hover a[href]
Элементы добавляют специфичность, подобную элементу (компонент `C`), псевдоклассы и атрибуты добавляют специфичность, подобную классу (компонент `B`). Существует 2 селектора элементов (2 × (0,0,1) ), селектор атрибута (value (0,0,1) ) и селектор класса (value (0,0,1) ). Это делает этот селектор имеющим общую специфичность (0,2,2) .

Прагматически увеличивая специфичность

Допустим, у вас есть CSS-код, который выглядит примерно так:

.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

С HTML, который выглядит так:

<button class="my-button" onclick="alert('hello')">Click me</button>

Кнопка имеет серый фон, потому что второй селектор имеет специфичность (0,1,1) . Это потому, что у нее есть один селектор типа ( button ), который равен (0,0,1) и селектор атрибута ( [onclick] ), который равен (0,1,0) .

Предыдущее правило — .my-button — равно (0,1,0) поскольку оно имеет один селектор класса, который имеет более низкую специфичность, чем (0,1,1) .

Если вы хотите усилить это правило, вы можете повторить селектор класса следующим образом:

.my-button.my-button {
  background: blue;
}

button[onclick] {
  background: grey;
}

Теперь кнопка будет иметь синий фон, так как новый селектор получает специфичность (0,2,0)

Связь по специфичности возвращается к следующему шагу в каскаде.

Продолжая пример с кнопкой, измените CSS следующим образом:

.my-button {
  background: blue;
}

[onclick] {
  background: grey;
}

Кнопка имеет серый фон, поскольку оба селектора имеют одинаковую специфичность (0,1,0) .

Если поменять правила в исходном порядке, кнопка станет синей.

[onclick] {
  background: grey;
}

.my-button {
  background: blue;
}

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

Ресурсы