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