Эффективный алгоритм сравнения специфичности правил CSS
Мне было интересно, какой эффективный алгоритм будет в следующем сценарии:
Задается разбираемый набор правил css, например.
p.pStyle{margin-bottom:20px;font-family:Arial;}
p{font-family:Verdana;}
p.anotherPStyle{margin-bottom:10px;}
Из таблицы стилей css возможно, что несколько наборов правил применяются к данному элементу (скажем, <p class="pStyle anotherPStyle">hello</p>
в моем документе).
p, pStyle and anotherPStyle
), а затем создать компаратор, способный сортировать применимые правила по спецификациям (от наиболее специфичных до самое-общее). Примечание: Я уже разработал алгоритм для применения правил после сортировки, поэтому вам не нужно эффективно решать эту проблему.
Я играл с несколькими идеями, а именно с одной, которая включает определение уровня в дереве DOM, к которому относится данное правило....Хотя я не уверен, что это правильный путь?
Как браузерный движок делает это эффективно? Я ищу, чтобы скопировать его на Java, но мне удобно со многими другими языками, так что любой код вы можете предложение наиболее ценится.
Спасибо
1 ответ:
Это определяется спецификой. В этом случае, поскольку они оба одинаково специфичны, объявление, которое приходит последним в файле, выигрывает.
Расчет Специфичности
Специфичность вычисляется путем ранжирования различных частей селектора .Ранжировано от наиболее специфичного к наименее:
- атрибут стиля - Если правило найдено в атрибуте стиля, этот ранг получает 1.
- ID-для каждого ID, найденного в селекторе, этот ранг получает дополнительный 1.
Классы, псевдоклассы, селекторы атрибутов-для каждого найденного в селекторе, этот ранг получает дополнительный 1.- элементы-для каждого элемента, найденного в селекторе, этот ранг получает дополнительный 1.
Где
rank n > rank n+1
, независимо от того, сколько очков имеет каждый ранг.Пример
ul#nav li.active a
Пункты следующие:
Таким образом, каждое свойство в этом селекторе имеет значение специфичности
- 0-не атрибут стиля.
- 1-1 ID найден.
- найдено 1-1 имя класса.
- 3 - Найдено 3 элемента.
[0,0,1,1,3]
(мы доберемся до этого дополнительного нуля через минуту). Это значение более специфично, чем любой селектор, если он может быть, например, без идентификатора.Алгоритм сравнения:
Идите слева направо по рядам. Сравните ранги на обоих селекторах.
- выигрывает тот ранг, у которого больше очков.
- если ранги равны, переходите сразу к следующему (менее конкретному) рангу.
- если все ранги равны, тот , который появляется позже в документе CSS, выигрывает.
Более важные Примечания:
Универсальный селектор
(*)
не имеет значения специфичности (0,0,0,0) псевдо-элементы (например,:first-line
) получают0,0,0,1
в отличие от их
псевдоклассовые братья, которые получают0,0,1,0
- псевдокласс
:not()
не добавляет специфичности сам по себе, только то, что внутри него скобки.- директива
!important
может быть применена к одиночному объявлению и добавляет точку к" 0-му " рангу, который более специфичен, чем что-либо
еще. Поэтому в приведенном выше примере добавление!important
к любому правилу будет
увеличьте значение специфичности только для этого правила до[1,0,1,1,2]
,
предоставление ему мгновенной победы над любыми другими правилами без!important
.Дополнительная Ссылка
См. эта замечательная статья на субъект
Как определить, какие стили переходят к какому элементу
Способ, которым браузер делает это, состоит в том, чтобы перейти по селектору отсправа налево и фильтровать элементы из DOM по мере их прохождения.
Возвращаясь к предыдущему примеру:
ul#nav li.active a
Браузер делает следующее:
Если для определенного элемента выполняются все эти условия, то к нему применяются стили.
- возьмите элемент
Теперь проверьте, есть ли у него предок, который является элементомa
.li
с классом.active
(это через комбинатор потомков:ancestor descendant
). Теперь проверьте, есть ли у него более высокий предок, который являетсяul
с идентификатором#nav
(снова используется комбинатор потомков).Вы можете прочитать его:
Выберите любой элемент
a
с предком с классом.active
, который также являетсяli
,
который в свою очередь имеет предка с идентификатором#nav
, который также являетсяul
.Вам потребуется иметь полностью функциональное и полное дерево DOM, чтобы успешно определить, какой элемент имеет какие стили CSS.