Почему браузеры соответствуют селекторам CSS справа налево?

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

  • Почему это?
  • Это только потому, что спецификация говорит?
  • Это влияет на возможный макет, если он был оценен слева направо?

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

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


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

Ответ 1

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

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

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

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

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

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

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

Ответ 2

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

Учтите следующее:

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

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

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

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

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

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

Ответ 3

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

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

Ответ 4

После того, как я немного покопался в Интернете, я пытаюсь сделать краткий вывод:

Когда селектор записи в файле CSS, слева направо, селектор должен стать более конкретным. Когда браузер читает файл CSS, он читает справа налево. Самый правый селектор в составном селекторе называется ключевым селектором.

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

Пожалуйста, помогите и поправьте меня.