В книге "Разгони свой сайт" тема производительности CSS-селекторов уже поднималась. Хотя все выводы были подкреплены значительный объемом исследований, но основной вопрос — как же должна выглядеть эффективная таблица стилей, которая обеспечивает наискорейшее отображение документа на экране - так и остался без ответа.
Для прояснения этой ситуации были проведены дополнительные условия, базирующиеся на уже известных фактах: наиболее эффективны селекторы, не использующие тегов, и классы работают быстрее, чем идентификаторы. Также известно, что селекторы обладают различной сложностью (например, .class1 .class2
, очевидно, должен отрабатывать медленнее, чем просто .class2
).
Для уточнения существенных факторов и относительного ранжирования извесных правил по написанию эффективного CSS-кода была взята за основу следующая формула:
Время отрисовки = Размер DOM-дерева * Число CSS-селекторов * Сложность стилевых правил * Время отрисовки одного правила + Время создания документа
Сразу при взгляде на эту формулу становится очевидным, что нам нужно брать усредненную сложность правил по всей таблице стилей, т.е. подставлять в формулу сумму сложностей всех CSS-селекторов, разделенную на их число.
Также практически сразу стало ясно, что в формуле фигурирует на размер всего DOM-дерева, а число элементов, на которые влияет данный селектор (это, в частности, объясняет, почему универсальный селектор, *
, такой ресурсоемкий). Для уточнения этого момента было проведен тест с одинаковым DOM-деревом и различными CSS-правилами (одно применялось ко всему дереву, а другое - только к десятой его части).
Еще не стоит забывать о наличии у браузеров собственной таблицы стилей, которая применяется к каждой странице, которая выводится на экран. Размер этой таблицы можно выяснить достаточно просто: нужно всего лишь открыть две страницы с разным ( и достаточно большим) числом CSS-правил, но одинаковым DOM-деревом и проверить, насколько замедлилась загрузка. Зная отношение размера двух таблиц стилей можно вычислить неизвестный размер таблицы стилей самого браузера (для основных браузеров он составил в районе 30-50 правил, для IE - порядка 200).
И еще один момент, который всплыл по ходу расследования: играет роль размер полного DOM-Дерева, не только число тегов, но и число текстовых узлов хотя это никак и не влияет на основные выводы.
В ходе проведения различных тестов модель удалось уточнить и показать, что время создания документа зависит от числа узлов в дереве (что вполне очевидно). Это можно проверить двумя наборами тестов: на увеличении числа CSS-селекторов без увеличения DOM-дерева и на увеличении DOM-дерева без увеличения числа CSS-селекторов. Хорошо видно, что время создания документа не является постоянным и несколько увеличивается при увеличении размера документа.
Также была проверена гипотеза, насколько составные селекторы отрабатывают медленнее своих элементарных собратьев (имеется в виду разница между .class1
, .class1 .class2
и .class1 .class2 .class3
). Разница была зафиксирована, но оказалась несущественной (каждое звено прибавляет примерно 10-20% к общей сложности селектора).
Итак, после всех уточнений формула приобрела следующий вид:
T = (сумма(DOM1 * K) + DOM2 * In) * t + DOM2 * L
Здесь:
T
— время отображения документа на экране.DOM1
— число элементов, на которое может повлиять данное CSS-правило (разбор CSS-правил в браузерах идет справа налево).DOM2
— размер всего DOM-дерева.K
— сложность каждого отдельного CSS-правила в таблице стилей, от 1 до 1,5.In
— число встроенных CSS-правил в браузере, порядка 40-200.t
— характерное время обработки одного правила для одного узла дерева, находится в районе 0,0001...0,0005 мс.L
— характерные издержки на создание одного элемента DOM-дерева, находятся в районе 0,0005...0,005 мс.Данная модель позволила аппроксимировать время отображения страницы с точностью 10% (в редких случаях 20%, видимо, есть еще много неучтенных факторов, например, особенности выделения памяти). Тестирование проводилось на документах от 5000 DOM-узлов и от 0 CSS-правил.
Анализ данной модели позволяет сделать огромное количество весьма интересных выводов, давайте, остановимся на некоторых из них:
*
) селектор и теги: они охватывают существенное количество элементов.ins
, del
, q
, u
, b
, i
).div
, для которых не нужны никаких правила по умолчанию, то переход от глобального «ластика» к локальному или вообще его устранение за счет индивидуальных правил способно несколько увеличить производительность).Также стоит отметить, что по результатам тестирования Виталия Харисова неиспользуемые CSS-правила добавляют некоторую задержку в отображении страницы (до 10% от времени отрисовки), поэтому их тоже стоит избегать.
Для средней HTML-страницы время ее отображения (размер DOM-дерева — 1000 элементов, CSS-правил — порядка 500, каждое из них в среднем применяется к 40% элементов) составит порядка 100мс. Простой оптимизацией можно уменьшить этот показатель вдвое (например, сузив область воздействия самих селекторов, если DOM-дерево уменьшить не получается).