Как CSS применяется браузером и влияет ли это на перерисовку? - PullRequest
31 голосов
/ 05 августа 2011

Допустим, у нас есть HTML-страница с одной таблицей стилей <link>. Как браузер берет правила в этой таблице стилей и применяет их к HTML? Я не спрашиваю о том, как сделать это быстрее, я хочу знать, как обрабатывается сам рендеринг.

Применяет ли оно каждое правило одно за другим, когда оно анализирует таблицу стилей и постепенно отображает результат? Или содержимое CSS-файла полностью загружено, затем полностью оценено, и , а затем применены к HTML сразу? Или что-то еще?

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

Я попробовал демо на моем сервере, которое выглядело так:

<!DOCTYPE html>
<html>
<head>
   <title>Test</title>
   <link rel="stylesheet" href="test.css" />
</head>
<body></body>
</html>

test.css содержание:

html { background:green }
/* thousands of lines of irrelevant CSS to make the download slow */
html { background:red }

Тестируя в Firefox 5, я ожидал сначала увидеть зеленый, а потом - красный. Этого не случилось Я попытался с двумя отдельными таблицами стилей с противоречивыми правилами и получил те же результаты. После многих комбинаций единственный способ заставить его работать - это встроенный блок <style> в <head>, с конфликтующими правилами из <link> в <body> (само тело было полностью пустым, за исключением тег ссылки). Даже использование встроенного атрибута style в теге <html> и последующая загрузка этой таблицы стилей не создали ожидаемого мелькания.

Повлияет ли перерисовка любым способом с помощью CSS, или окончательный результат применяется сразу после загрузки всей таблицы стилей, и его правила вычисляются в соответствии с тем, каким должен быть конечный результат? Файлы CSS загружаются параллельно с самим HTML или блокируют его (как это делают теги скрипта)? Как это на самом деле работает?

Я не ищу советы по оптимизации, я ищу авторитетные ссылки на эту тему, чтобы я мог ссылаться на них в будущем. Было очень трудно искать эту информацию, не найдя тонны несвязанного материала. Краткое описание:

  • Весь ли контент CSS загружен до какого-либо его применения? (ссылка, пожалуйста)
  • Как на это влияют такие вещи, как @import, несколько <link> s, атрибуты встроенного стиля, <style> блоки в голове и различные механизмы рендеринга?
  • Блокирует ли загрузка содержимого CSS загрузку самого документа HTML?

Ответы [ 3 ]

16 голосов
/ 05 августа 2011

Как браузер берет правила в этой таблице стилей и применяет их к HTML?

Обычно это делается потоковым способом. Браузер считывает теги HTML как поток и применяет все возможные правила к элементам, которые он видел до сих пор. (Очевидно, это упрощение.)

Интересные вопросы и ответы: Использование CSS-селекторов для сбора HTML-элементов из потокового синтаксического анализатора (например, потока SAX) (отклонение при поиске статьи, о которой я думаю).


Ах, вот оно: Почему у нас нет родительского селектора .

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

Взгляните на тело примера документа:

<body>
   <div id="content">
      <div class="module intro">
         <p>Lorem Ipsum</p>
      </div>
      <div class="module">
         <p>Lorem Ipsum</p>
         <p>Lorem Ipsum</p>
         <p>Lorem Ipsum <span>Test</span></p>
      </div>
   </div>
</body>

Браузер запускается сверху и видит элемент body. С этой точки зрения, он думает, что он пуст. Он не оценил ничего другого. Браузер определит, что такое вычисленные стили, и применит их к элемент. Какой шрифт, цвет, высота строки? После этого выясняет это, он рисует его на экране.

Затем он видит элемент div с идентификатором content. Опять же на этом точка, он думает, что это пусто. Он не оценил ничего другого. Браузер выясняет стили, а затем div раскрашивается. браузер определит, нужно ли перекрашивать тело - сделал элемент стать шире или выше? (Я подозреваю, что есть и другие соображения, но изменения ширины и высоты являются наиболее распространенными эффектами дочерних элементов есть на своих родителей.)

Этот процесс продолжается, пока не достигнет конца документа.

image

CSS оценивается справа налево.

Чтобы определить, применяется ли правило CSS к определенному элементу, начинается справа от правила и работает влево.

Если у вас есть правило типа body div#content p { color: #003366; }, тогда для каждого элемента, когда он отображается на странице, он сначала спросит, это элемент абзаца. Если это так, он будет работать до DOM и спросите, если это div с идентификатором контента. Если он находит то, что ищет ибо он продолжит свой путь вверх по DOM, пока не достигнет body.

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


Так почему же содержимое таблицы стилей не применялось постепенно (сначала зеленым, а затем красным)?

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

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

9 голосов
/ 05 августа 2011

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

Теперь веб-страница читается как поток, и правила CSS применяются к элементам HTML по мере их поступления на страницу. Чтобы процитировать статью Google по ссылке ниже:

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

Итак, теперь ответьте на ваши вопросы:

Применяет ли оно каждое правило одно за другим, когда оно анализирует таблицу стилей и постепенно отображает результат? Или содержимое файла CSS полностью загружено, затем полностью оценено и затем применено к HTML сразу? Или что-то еще?

Загружает весь CSS, затем начинает рисовать документ сверху вниз.

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

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

После многих комбинаций единственный способ заставить его работать - это встроенный блок <style> в <head>, с конфликтующими правилами из <link> в <body>

Хотя я не могу точно сказать, почему это произошло, я думаю, что браузер не искал CSS в теге body, начал рисовать, встретил CSS тела, затем перекрасил.

CSS каким-либо образом влияет на перерисовку?

Честно говоря, я бы больше беспокоился о том, что JS вызвал перекрашивание. Но если у вас очень большой DOM, имеет смысл структурировать ваш CSS таким образом, чтобы вы не вызывали рефлоки из-за странного позиционирования. @Matt дал вам несколько хороших ссылок на эту тему Некоторые хорошие ресурсы:

http://www.dayofjs.com/videos/22158462/web-browsers_alex-russel Алекс Рассел подробно рассказывает о том, как webkit анализирует CSS, как работает перекомпоновка и перерисовка и что их вызывает.

http://code.google.com/speed/page-speed/docs/rendering.html Это основная статья о том, как оптимизировать CSS-рендеринг

1 голос
/ 12 июня 2015

Я не уверен насчет помеченного ответа. Я сомневаюсь, что это правильно. Согласно этой ссылке от Google Developers браузер сначала загружает файл HTML, а когда он видит файл CSS, связанный с внешним ресурсом, он начинает загрузку файла CSS, одновременно создавая структуру DOM для данного файла HTML как CSS не повлияет на DOM. Обратите внимание, что он не применяет никаких стилей к документу, когда браузер загружает файл CSS.

После загрузки файла CSS (предположим, что нет файлов сценариев) и, если построение DOM завершено, браузер начинает сопоставлять свойства CSS с этими узлами в дереве DOM. После этого он создает другое дерево с именем Render tree, которое строит все объекты, которые должны отображаться, в виде прямоугольников. Только после завершения дерева рендера оно начинает рисовать на экране.

Подведем итог:

  • Браузер полностью загружает файл CSS.
  • Браузер не применяет стили к странице при загрузке. Только после завершения загрузки он начинает отображать правила.
  • Правила применяются только на этапе построения дерева рендеринга.
  • Загрузка файла CSS не блокирует загрузку HTML. Вы должны отметить, что браузер

Сначала загружаются все html-файлы, а затем загружаются файлы стилей и сценариев.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...