Почему браузеры соответствуют CSS-селекторам справа налево? - PullRequest
530 голосов
/ 27 апреля 2011

CSS-селекторы соответствуют браузерным движкам справа налево. Поэтому они сначала находят детей, а затем проверяют своих родителей, чтобы убедиться, что они соответствуют остальным частям правила.

  1. Почему это?
  2. Это только потому, что в спецификации написано?
  3. Влияет ли это на конечный макет, если он был оценен слева направо?

Для меня самый простой способ сделать это - использовать селекторы с наименьшим количеством элементов. Поэтому сначала идентификаторы (так как они должны возвращать только 1 элемент). Тогда, возможно, классы или элемент, который имеет наименьшее количество узлов - например, на странице может быть только один промежуток, поэтому перейдите непосредственно к этому узлу с любым правилом, ссылающимся на промежуток.

Вот несколько ссылок, подтверждающих мои претензии

  1. http://code.google.com/speed/page-speed/docs/rendering.html
  2. https://developer.mozilla.org/en/Writing_Efficient_CSS

Похоже, что это сделано таким образом, чтобы не смотреть на всех детей родителя (которых может быть много), а не на всех родителей ребенка, который должен быть одним. Даже если DOM является глубоким, он будет рассматривать только один узел на уровень, а не несколько при сопоставлении RTL. Легче / быстрее оценивать CSS-селекторы LTR или RTL?

Ответы [ 3 ]

797 голосов
/ 28 апреля 2011

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

Если у вас был только один селектор и только один элемент для сравнения с этимСелектор, то слева направо имеет больше смысла в некоторых случаях.Но это решительно не ситуация браузера.Браузер пытается отобразить Gmail или что-то еще, и у него есть одно <span>, которое он пытается стилизовать, и более 10000 правил, которые Gmail вставляет в свою таблицу стилей (я не придумываю это число).

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

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

С другой стороны, если вы начинаете с сопоставления самой левой частиселектор ... с чем ты сравниваешь?Вы должны начать ходить по DOM, ища узлы, которые могут ему соответствовать.Просто обнаружение, что ничто не соответствует этой самой левой части, может занять некоторое время.

Так что браузеры совпадают справа;это дает очевидную отправную точку и позволяет очень быстро избавиться от большинства кандидатов на выбор.Вы можете увидеть некоторые данные в http://groups.google.com/group/mozilla.dev.tech.layout/browse_thread/thread/b185e455a0b3562a/7db34de545c17665 (хотя обозначения сбивают с толку), но в результате получается, что для Gmail, в частности два года назад, для 70% пар (правило, элемент) вы могли решить, что правилоне совпадает только после проверки частей тега / класса / идентификатора крайнего правого селектора для правила.Соответствующий показатель для набора тестов производительности загрузки страниц Mozilla составил 72%.Так что действительно стоит попытаться избавиться от этих 2/3 всех правил как можно быстрее, а затем беспокоиться только о соответствии оставшимся 1/3.

Обратите внимание, что есть и другие оптимизации, которые браузеры уже делают дляизбегайте даже попыток соответствовать правилам, которые точно не будут соответствоватьНапример, если у крайнего правого селектора есть идентификатор, и этот идентификатор не совпадает с идентификатором элемента, то в Gecko вообще не будет попытки сопоставить этот селектор с этим элементом: набор «селекторов с идентификаторами», которые предпринимаютсяисходит из поиска по хеш-таблице идентификатора элемента.Так что это 70% правил, которые имеют довольно хорошие шансы на совпадение, что все еще не совпадают после рассмотрения только тега / класса / id самого правого селектора.

28 голосов
/ 18 февраля 2014

Разбор справа налево, также называемый анализ снизу вверх , фактически эффективен для браузера.

Рассмотрим следующее:

#menu ul li a { color: #00f; }

Браузер сначала проверяет a, затем li, затем ul, а затем #menu.

Это потому, что, поскольку браузер сканирует страницу, ему просто нужно посмотреть текущий элемент / узел и все предыдущие узлы / элементы, которые он сканировал.

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

Если это сделать наоборот, это будет неэффективно, поскольку браузер обнаружил элемент, который он сканировал при первой проверке, но затем был вынужден продолжить просмотр документа для всех дополнительных селекторов. Для этого браузер должен иметь весь html и, возможно, потребуется отсканировать всю страницу, прежде чем он начнет рисовать css.

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

19 голосов
/ 27 апреля 2011

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

Если бы вы пошли другим путем, вы бы форматировали в соответствии с родителем, а затем перезаписывали каждый раз, когда у ребенка что-то другое.В конечном счете, это гораздо больше работы, чем игнорирование элементов в правилах, о которых уже позаботились.

...