Заблуждения о Специфичности CSS
Однако иногда я также поднимаю бровь, поскольку иногда, к сожалению, сталкиваюсь с тем, что просто откровенно неправильно.
Чтобы устранить путаницу, вот список заблуждений о Специфичности в CSS…
Заблуждение 1: Специфичность — это десятичная оценка
В некоторых, обычно старых, статьях Специфичность выражается в десятичной оценке или упоминается, что такая вещь, как селектор классов, добавляет 10 очков
. Это неточно, поскольку подразумевается, что 11 селекторов элементов с их 1 баллом за каждый
победят 1 селектор класса, который имеет только 10 баллов
.
Вместо этого Специфичность — это триплет (или триада), состоящий из трёх компонентов: A
, B
и C
. Значения A
, B
и C
зависят от того, какой тип селектора вы используете.
A
= специфичность идентификатораB
= специфичность классаC
= специфичность элемента
Её часто представляют с помощью нотации (A,B,C)
. Например: (1,0,2)
. Также часто используется альтернативная нотация A-B-C
.
🤓 Я написал библиотеку JavaScript, которая может вычислять специфичность селектора: @bramus/specificity. Она используется в этом интерактивном калькуляторе специфичности.
Специфичность сравнивается путём сопоставления трёх компонентов по порядку: специфичность с большим значением A является более специфичной; если два значения A равны, то специфичность с большим значением B является более специфичной; если два значения B также равны, то специфичность с большим значением C является более специфичной; если все значения равны, то две специфичности равны.
В коде это выглядит так:
const compare = (s1, s2) => {
if (s1.a === s2.a) {
if (s1.b === s2.b) {
return s1.c - s2.c;
}
return s1.b - s2.b;
}
return s1.a - s2.a;
};
Например, (1,0,0)
обладает более высокой специфичностью, чем (0,10,3)
, поскольку значение A
в (1,0,0)
(равное 1
) больше, чем значение A
из (0,10,3)
(равное 0
).
Также посмотрите этот отрывок из моего выступления на CSS Day 2022 о каскаде:
💡 Хотя вы можете представить триаду в виде десятеричного числа, добавив достаточное количество ведущих нулей, это сопряжено с определёнными трудностями: число, которое вы получите в итоге, трудно читать/разбирать + вам нужно будет добавить «достаточно» нулей, чтобы получить корректно сортируемый результат.
Мой совет: не надо.
Откуда взялась путаница
Ещё в CSS Selectors 3, в спецификации упоминалось, что можно объединять числа, для получения специфичности.
Конкатенация трёх чисел a-b-c (в системе счисления с большим основанием) даёт специфичность.
* /* a=0 b=0 c=0 -> специфичность = 0 */
LI /* a=0 b=0 c=1 -> специфичность = 1 */
UL LI /* a=0 b=0 c=2 -> специфичность = 2 */
UL OL+LI /* a=0 b=0 c=3 -> специфичность = 3 */
H1 + *[REL=up] /* a=0 b=1 c=1 -> специфичность = 11 */
UL OL LI.red /* a=0 b=1 c=3 -> специфичность = 13 */
LI.red.level /* a=0 b=2 c=1 -> специфичность = 21 */
#x34y /* a=1 b=0 c=0 -> специфичность = 100 */
#s12:not(FOO) /* a=1 b=0 c=1 -> специфичность = 101 */
Хотя оговорка в системе счисления с большим основанием
была проигнорирована, скорее всего, потому, что в спецификации были приведены примеры с основанием 10 — например, #s12:not(FOO) /* a=1 b=0 c=1 -> specificity = 101 */
.
Прошло почти 15 лет, а мы до сих пор не можем с этим справиться: некоторые авторы продолжают представлять Специфичность в базе 10, потому что это проще для объяснения
. Возможно, это и так, но это учит людей неправильным вещам. Впоследствии заставить их переучиваться гораздо сложнее.
Заблуждение 2: Использование атрибута style
добавляет Специфичности
Я часто читаю, что использование атрибута style
добавляет 1000 пунктов специфичности
. Это неверно, поскольку оценка атрибута style
является более ранним шагом каскада — она вообще не имеет отношения к специфичности.
Откуда взялась путаница
Во времена CSS2 (в 2011 году) это было действительно так. В той спецификации Специфичность была четверной (A, B, C, D), атрибут style
был компонентом A.
Однако с появлением CSS3 это уже не так.
Заблуждение 3: Использование !important
добавляет Специфичности
Я часто читаю, что добавление !important
к декларации «добавляет 10000 пунктов специфичности». Это неверно, так как использование !important
помещает декларацию в другой источник. При использовании !important
в авторских стилях декларация переходит из источника Normal Author Declarations в источник Important Author Declarations.
Источники и важность — это первый критерий каскада, который проверяется. Специфичность появляется гораздо позже.
Откуда взялась путаница
Я не смог найти никаких следов в спецификациях, но предполагаю, что кто-то придумал это в те времена, когда критерий Специфичность напрямую следовал за критерием Источники/Origins. Тогда такое упрощение имело смысл, но сейчас оно уже не имеет смысла, поскольку пропускает три дополнительных критерия каскада, которые находятся между Источниками+Важность и Специфичностью: Контекст, Стили прикреплённые к элементу, и Слои.
Узнать больше
Чтобы узнать больше о Специфичности и Каскаде, рекомендую посмотреть доклад, который я делал на CSS Day 2022 и в нем рассказывается обо всем, что нужно знать об этом.
В статье The CSS Cascade: A Deep Dive (2022.06.09 @ CSS Day) на сайте https://www.bram.us/ также можно посмотреть слайды.