Подкаст 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 является более специфичной; если два значения 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
(0,0,2)
.article.card.dark
(0,2,1)
.article:hover a[href]
(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;
}
Это связано с тем, что оба селектора имеют одинаковую специфичность. В этом случае каскад возвращается к шагу порядка появления .