Выбор эффективных селекторов на основе вычислительной сложности

Учитывая особенности обработки CSS, в частности, соответствие RTL и эффективность селекторов, как следует писать селекторы исключительно с точки зрения производительности движка рендеринга?

Это должно охватывать общие аспекты и включать использование или избегание псевдоклассов, псевдоэлементов и селекторов отношений.

1 ответ

Решение

Во время выполнения HTML-документ анализируется в DOM-дереве, содержащем N элементы со средней глубиной D, Существует также в общей сложности S Правила CSS в применяемых таблицах стилей.

  1. Стили элементов применяются индивидуально, что означает прямую связь между N и общая сложность. Стоит отметить, что это может быть несколько компенсировано логикой браузера, такой как эталонное кэширование и переработка стилей из идентичных элементов. Например, к следующим элементам списка будут применены те же свойства CSS (при условии отсутствия псевдоклассов, таких как :nth-child применяются):

    <ul class="sample">
      <li>one</li>
      <li>two</li>
      <li>three</li>
    </ul>
    
  2. Селекторы сопоставляются справа налево для соответствия отдельным правилам - т. Е. Если самый правый ключ не соответствует определенному элементу, нет необходимости дополнительно обрабатывать селектор, и он отбрасывается. Это означает, что самый правый ключ должен соответствовать как можно меньшему числу элементов. Ниже p дескриптор будет соответствовать большему количеству элементов, включая абзацы за пределами целевого контейнера (что, конечно, не будет применять правило, но все равно приведет к большему количеству итераций проверки приемлемости для этого конкретного селектора):

    .custom-container p {}
    .container .custom-paragraph {}
    
  3. Селекторы отношений: селектор потомков требует до D элементы для повторения. Например, удачное совпадение .container .content может потребоваться только один шаг, если элементы находятся в родительско-дочерних отношениях, но дерево DOM необходимо будет пройти через весь путь до html прежде чем элемент может быть подтвержден несоответствие и правило безопасно отбрасывается. Это относится и к цепочечным селекторам потомков, с некоторыми допусками.

    С другой стороны, > выбор ребенка, + соседний селектор или :first-child все еще требует, чтобы дополнительный элемент был оценен, но имеет только подразумеваемую глубину один и никогда не потребует дальнейшего обхода дерева.

  4. Определение поведения псевдоэлементов, таких как :before а также :after подразумевает, что они не являются частью парадигмы RTL. Логика заключается в том, что псевдоэлемента как такового не существует, пока правило не даст указание вставить его до или после содержимого элемента (что, в свою очередь, требует дополнительных манипуляций с DOM, но для соответствия самому селектору не требуется никаких дополнительных вычислений).

  5. Я не мог найти информацию о псевдоклассах, таких как :nth-child() или же :disabled, Проверка состояния элемента потребовала бы дополнительных вычислений, но с точки зрения синтаксического анализа правила имело бы смысл только исключить их из обработки RTL.

Учитывая эти отношения, вычислительная сложность O(N*D*S) должен быть снижен в первую очередь за счет минимизации глубины селекторов CSS и адресации пункта 2 выше. Это приведет к значительно более сильным улучшениям по сравнению с минимизацией количества правил CSS или только элементов HTML.

Мелкие, предпочтительно одноуровневые, специфические селекторы обрабатываются быстрее. Это подняло Google на совершенно новый уровень (программно, а не вручную!), Например, редко есть селектор с тремя ключами, и большинство правил в результатах поиска выглядит так

#gb {}
#gbz, #gbg {}
#gbz {}
#gbg {}
#gbs {}
.gbto #gbs {}
#gbx3, #gbx4 {}
#gbx3 {}
#gbx4 {}
/*...*/

^ - хотя это верно с точки зрения производительности движка рендеринга, всегда есть дополнительные факторы, такие как издержки трафика, анализ DOM и т. д.

Источники: 1 2 3 4 5

Другие вопросы по тегам