Как рассчитываются баллы за специфичность CSS

125

Исследуя специфичность, я наткнулся на этот блог - http://www.htmldog.com/guides/cssadvanced/specificity/

В нем говорится, что специфичность - это система баллов для CSS. Он сообщает нам, что элементы приносят 1 балл, классы приносят 10 баллов, а идентификаторы приносят 100 баллов. Сверху также говорится, что эти баллы суммированы, и общая сумма зависит от специфики этого селектора.

Например:

body = 1 балл
body .wrapper = 11 баллов
body .wrapper #container = 111 баллов

Итак, используя эти точки, я ожидаю, что следующие CSS и HTML приведут к тому, что текст будет синим:

#a {
    color: red;
}

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o {
  color: blue;
}
<div class="a">
  <div class="b">
    <div class="c">
      <div class="d">
        <div class="e">
          <div class="f">
            <div class="g">
              <div class="h">
                <div class="i">
                  <div class="j">
                    <div class="k">
                      <div class="l">
                        <div class="m">
                          <div class="n">
                            <div class="o" id="a">
                              This should be blue.
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Почему текст красный, если 15 классов равны 150 баллам по сравнению с 1 идентификатором, равным 100 баллам?

Очевидно, очки не просто суммируются; они связаны. Подробнее об этом читайте здесь - http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

Означает ли это, что классы в нашем селекторе = 0,0,15,0ИЛИ 0,1,5,0?

(мои инстинкты говорят мне , что это первое, как мы знаем специфичность выглядит селектор как это: 0,1,0,0)

Сэм
источник
Вот и кое-что странное: stackoverflow.com/questions/25565928/…
Армель Ларсье

Ответы:

138

Ответ Пекка в это практически правильно, и , вероятно , лучший способ думать о проблеме.

Однако, как многие уже отметили, рекомендация W3C CSS гласит: «Объединение трех чисел abc (в системе счисления с большим основанием) дает конкретность». Так что компьютерщик во мне просто должен был выяснить, насколько велика эта база.

Оказывается, что «очень большая база», используемая (по крайней мере, в 4 наиболее часто используемых браузерах * ) для реализации этого стандартного алгоритма, составляет 256 или 28 .

Это означает, что стиль, указанный с 0 идентификаторами и 256 именами классов, будет иметь приоритет над стилем, указанным только с 1 идентификатором. Я проверил это на нескольких скрипках:

Таким образом, фактически существует «балльная система», но это не система счисления 10. Это система счисления 256. Вот как это работает:

(2 8 ) 2 или 65536, умноженное на количество идентификаторов в селекторе
+ (2 8 ) 1 или 256, умноженное на количество имен классов в селекторе
+ (2 8 ) 0 или 1, умноженное на количество тегов- имена в селекторе

Это не очень практично для упражнений на обратной стороне конверта для передачи концепции.
Вероятно, поэтому в статьях по этой теме используется база 10.

***** [Opera использует 2 16 (см. Комментарий karlcow). Некоторые другие селекторные механизмы используют бесконечность - фактически без балльной системы (см. Комментарий Саймона Сапина).]

Обновление, июль 2014 г .:
как ранее в этом году Блейзмонгер указал, браузеры webkit (chrome, safari) теперь, похоже, используют базу выше 256. Возможно, 2 16 , как Opera? IE и Firefox по-прежнему используют 256.

Faust
источник
34
Важно: обратите внимание, что число 256 не указано в спецификации . Таким образом, этот ответ описывает (по общему признанию, полезную) деталь реализации.
Мэтт Фенвик,
6
Не только 256 не входит в спецификацию, как сказал @MattFenwick, но и варьируется в зависимости от реализации. В Опере видимо больше. В WeasyPrint и cssselect это «бесконечность»: я использую кортеж целых чисел вместо одного целого числа.
Саймон Сапин
3
@Faust Opera использует 16 бит вместо 8
karlcow
4
Если честно, этот ответ имеет более практическое описание, чем ответ Пекки. В основном то, что говорит @Matt Fenwick: то, что вы описываете, является практической реализацией спецификации. При этом он ошибочный, но не тот, с которым что-либо должно быть сделано, будь то авторы или разработчики.
BoltClock
7
256 кажется недостаточным в текущих версиях webkit (Chrome и Safari), что еще раз подчеркивает точку зрения @MattFenwick.
Blazemonger
28

Хороший вопрос.

Я не могу сказать наверняка - все статьи, которые мне удалось найти, избегают примера нескольких классов, например здесь, - но я предполагаю, что когда дело доходит до сравнения специфичности между селектором класса и идентификатором , класс вычисляется с помощью 15только значение , независимо от того, насколько оно детализировано.

Это соответствует моему опыту в том, как ведет себя специфичность.

Однако должно быть некоторое наложение классов, потому что

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o

более конкретен, чем

.o

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

Обновление : я на полпути понял. Это не балльная система, и информация о классах с весом 15 баллов неверна. Это система нумерации 4-часть очень хорошо объяснено здесь .

Отправная точка - 4 цифры:

style  id   class element
0,     0,   0,    0

Согласно объяснению специфичности W3C , значения специфичности для вышеупомянутых правил следующие:

#a            0,1,0,0    = 100
classes       0,0,15,0   = ... see the comments

это система нумерации с очень большой (неопределенной?) базой.

Насколько я понимаю, поскольку база очень большая, никакое число в столбце 4 не может превзойти число> 0 в столбце 3, то же самое для столбца 2, столбца 1 .... Это правильно?

Мне было бы интересно, мог бы кто-нибудь с большим пониманием математики, чем я, объяснить эту систему счисления и как преобразовать ее в десятичную, когда отдельные элементы больше 9.

Пекка
источник
Это потому, что он находится между .o и .a .b и т. Д. Поэтому он будет рассматривать их вместе. Но между идентификатором и классом, например: .a и #a, идентификатор всегда будет преобладать. Я предполагаю, что он будет учитываться только между классами, когда нет более сильного атрибута. Например, класс будет проходить над элементом и идентификатором над классом.
Sphvn
@Ozaki это то, что я тоже предполагаю, но это противоречит тому, что OP говорит о системе баллов. В игре должно быть больше. Я хотел бы увидеть правила, стоящие за этим.
Пекка
Только что понял, что мы оба пришли к одному выводу. Превосходная работа!
Сэм
5
Что касается математики, здесь мы можем работать с основанием 16 (потому что ни одно из отдельных чисел не превышает 15). Итак, 0,1,0,0 = 0100h = 256 0,0,15,0 = 00f0h = 240 256> 240, поэтому селектор id выигрывает.
Мэтью Уилсон,
1
Да, вы можете думать о расчетах специфичности, как о выполняемых в системе счисления с большой базой. Я думаю, что термин «конкатенация» (также используемый в спецификации) - гораздо лучшее описание. (Пришел сюда после того, как ответил на новый вопрос, который, как выяснилось, был обманом,
подумайте
9

Текущий рабочий черновик Selectors Level 4 хорошо описывает специфичность CSS:

Специфичность сравнивается путем сравнения трех компонентов по порядку: специфичность с большим значением A является более специфичной; если два значения A связаны, то специфичность с большим значением B более конкретна; если два значения B также связаны, то специфичность с большим значением c более конкретна; если все значения связаны, две особенности равны.

Это означает, что значения A, B и C полностью независимы друг от друга.

15 классов не дают вашему селектору 150 баллов за специфичность, они дают ему значение B, равное 15. Одного значения A достаточно, чтобы преодолеть это.

В качестве метафоры представьте себе семью из 1 главного родителя, 1 родителя и 1 ребенка. Это может быть представлено как 1,1,1 . Если у родителя 15 детей, это не делает их еще одним родителем ( 1,2,0 ). Это означает, что на родителях лежит гораздо больше ответственности, чем с одним ребенком ( 1,1,15 ). ;)

В той же документации также говорится:

Из-за ограничений хранилища реализации могут иметь ограничения на размер A , B или c . Если это так, значения, превышающие предел, должны быть ограничены этим пределом, а не переполнены.

Это было добавлено для решения проблемы, представленной в ответе Фауста , в результате чего реализации CSS еще в 2012 году позволяли значениям специфичности перетекать друг в друга.

Еще в 2012 году в большинстве браузеров было реализовано ограничение 255, но это ограничение допускало переполнение. 255 классов имели A, B, C специфичность балла 0,255,0 , но 256 классов переполнены и имели А, B, C балл 1,0,0 . Внезапно наш B значение стало нашим значением. Документация Selectors Level 4 полностью освещает эту проблему, заявляя, что предел никогда не может выйти за пределы. С этой реализацией, как 255 и 256 классов будут иметь тот же A, B, C балл 0,255,0 .

Проблема, указанная в ответе Фауста, с тех пор исправлена в большинстве современных браузеров.

Джеймс Доннелли
источник
8

В настоящее время я использую книгу « Мастерство CSS: передовые решения для веб-стандартов» .

Глава 1, страница 16 говорит:

Чтобы вычислить, насколько конкретным является правило, каждому типу селектора присваивается числовое значение. Затем специфика правила вычисляется путем сложения значений каждого из его селекторов. К сожалению, специфичность рассчитывается не по основанию 10, а по высокому, неуказанному основному числу. Это необходимо для того, чтобы такой селектор с высокой степенью специфичности, как селектор идентификатора, никогда не переопределялся множеством менее специфичных селекторов, таких как селекторы типов.

(курсив мой) и

Специфика селектора разбита на четыре составляющих уровня: a, b, c и d.

  • если это встроенный стиль, тогда a = 1
  • b = общее количество селекторов id
  • c = количество селекторов классов, псевдоклассов и атрибутов
  • d = количество селекторов типа и селекторов псевдоэлементов

Далее говорится, что вы часто можете выполнять вычисления в базе 10, но только если все столбцы имеют значения меньше 10.


В ваших примерах идентификаторы не приносят 100 баллов; каждый стоит [0, 1, 0, 0]очков. Следовательно, один идентификатор [0, 1, 0, 0]лучше 15 классов, потому что он больше, чем [0, 0, 15, 0]в системе с большим числом оснований.

Мэтт Фенвик
источник
4

Мне нравится сравнивать рейтинг Специфичности с таблицей медалей Олимпийских игр (метод сначала золото - сначала по количеству золотых медалей, затем серебряных, а затем бронзовых).

Это работает и с вашим вопросом (огромное количество селекторов в одной группе специфики). Специфика рассматривалась каждой группой в отдельности. В реальном мире я очень редко встречал случаи с более чем десятком селекторов).

Существует также довольно хороший калькулятор Специфичность доступны здесь . Вы можете поместить туда свой пример (#a и .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o) и посмотреть результаты.

Пример таблицы медалей Олимпийских игр в Рио-2016 выглядит так введите описание изображения здесь

rkarczmarczyk
источник
3

Я не верю, что объяснение в блоге правильное. Спецификация здесь:

http://www.w3.org/TR/CSS2/cascade.html#specificity

«Очки» из селектора класса не могут быть более важными, чем селектор «id». Это просто так не работает.

Мэтью Уилсон
источник
Как я сказал в своем ответе. ^^ Однако есть разница, есть ли у вас несколько экземпляров того же типа (элемент, класс, идентификатор). Но это довольно очевидно, если пятеро говорят красное, а трое - синее, ну, има становится красным.
Sphvn
Формулировка, касающаяся специфичности, вероятно, не сильно изменилась между CSS2 и CSS2.1, но вы действительно должны указать на спецификацию CSS2.1 в будущих обсуждениях, поскольку она полностью заменяет CSS2, который в целом был нарушен на момент выпуска.
Робин Уиттлтон,
1

Я бы сказал, что:

Element < Class < ID

Я думаю, они складываются только в зависимости от того, что вы получаете, если оно кратно одному и тому же. Таким образом, класс всегда будет перекрывать элемент и идентификатор всегда над классом, но если он ограничен тем, какой из 4 элементов, где 3 - синий, а 1 - красный, он будет синим.

Например:

.a .b .c .d .e .f .g .h .i .j .k .l
{
color: red;
}

 .m .n .o
{
color blue;
}

Должно получиться красным.

См. Пример http://jsfiddle.net/RWFWq/

"если пятеро говорят красное, а трое говорят синее, хорошо, я иду красным"

Sphvn
источник