Подкаст 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 является более специфичной; если два значения 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;
}
селектор идентификатора
Селектор ID добавляет специфичность, подобную идентификатору , увеличивая компонент A на 1, при условии, что вы используете селектор ID ( #myID ), а не селектор атрибута ( [id="myID"] ).
В следующем примере специфичность равна (1,0,0)
#myID {
color: red;
}
Другие селекторы
В CSS много селекторов. Не все из них добавляют специфичность. Например, сам псевдокласс :not() ничего не добавляет к расчету специфичности.
Специфичность псевдокласса :not() заменяется специфичностью наиболее специфичного селектора в его аргументе селекторов, разделенном запятыми; обеспечивая ту же специфичность, как если бы он был написан :not(:is(argument)) .
div:not(.my-class) {
color: red;
}
Псевдокласс :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() отличается. Независимо от специфичности любого из его аргументов, он всегда имеет специфичность (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>
Чтобы переопределить это объявление из таблицы стилей, необходимо добиться того, чтобы объявление имело приоритет на более раннем этапе каскада .
Например, вы можете добавить к нему !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,1,0) ) и селектор класса (значение (0,1,0) ). Таким образом, общая специфичность этого селектора составляет (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;
}
Это происходит потому, что оба селектора имеют одинаковую специфичность. В этом случае каскад возвращается к порядку появления .