Специфика

Подкаст CSS – 003: Специфика

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

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

button {
  color: red;
}

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

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

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

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

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

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

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

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

Его часто представляют с использованием обозначений (A,B,C) . Например: (1,0,2) . Альтернативное обозначение ABC также широко используется.

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

Сравнение особенностей

Специфичность сравнивается путем сравнения трех компонентов по порядку: специфичность с большим значением А является более специфичной; если два значения 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;
}

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

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

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

#myID {
  color: red;
}

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

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

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

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

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

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

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

В чем специфика 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,1) , что составляет общую специфичность (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) ), селектор атрибута (стоимость (0,0,1) ) и селектор класса (стоимость (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;
}

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

Ресурсы