[БЕЗ_ЗВУКА] Мы все ближе приближаемся к конечному результату, который пользователь увидит на экране браузера. Но для того чтобы понимать, как он формируется, давайте рассмотрим, как внутри браузера устроен движок rendering. Для этого важно понимать, что браузеры внутри себя содержат разные движки rendering. Браузер Microsoft Edge содержит внутри себя движок рендеринга, который называется EdgeHTML. Браузер Firefox содержит движок, который называется Gecko. Safari содержит движок Webkit. Браузеры на основе Chromium содержат движок Blink. Здесь важная ремарка: Blink является форком Webkit, то есть какие-то особенности поведения у них могут быть одинаковыми, а какие-то могут быть разными. И наконец браузер Opera Mini содержит движок Presto. Здесь я тоже хотел бы обратить ваше внимание, что браузер Opera десктопный использует движок Blink, а браузер Opera Mini — свой самописный движок Presto. Каждый браузер внутри себя содержит определенный набор модулей, которые в итоге позволяют отрендерить результат. Этот набор модулей в целом похож, только названия у них немножко отличаются. Вы можете даже сопоставить названия этих модулей внутри браузеров Google Chrome и Firefox. Как вы можете увидить, здесь за редким исключением последовательность действий одинакова. Почему важно это понимать? Потому что в вебе, так получилось, что прижились разные термины. Например, мы говорим, что браузер формирует Render Tree, но при этом процесс компоновки страницы называется reflow. Итак, давайте же пойдем немножко глубже и поговорим о том, как браузеры анализируют документ. Первое, что делает браузер, после того как получает данные, он их «распаршливает», то есть понимает, как байты транслируются в символы. Получив последовательность символов, браузер начинает процесс токенизации. То есть он идет по каждому символу и выделяет смысловые единицы. Например, последовательность символов: символ «меньше», html, символ «больше» — это токен открывающего тега html и так далее. Сформулировав токены, браузер формулирует узлы, или «ноды». И уже после этого, в зависимости от того, какой элемент как вложен друг в друга, браузер формулирует DOM-дерево — Document Object Model. Именно основываясь на DOM-дереве, далее браузер будет рендерить страницу. Я хочу обратить ваше внимание, что, например, в DOM-дереве текст, внутри которого у нас находится инлайновый элемент, также делится на отдельные ноды. Это важно. Что еще важно понимать? Внутри браузера заложен так называемый щадящий алгоритм, то есть вы не увидите ошибку, если вдруг в вашем html есть где-то какая-то неточность. Например, вы неправильно использовали закрывающий тег, закрывающего тега </br> нет. Браузер в данном случае исправит эту ошибку за вас и отобразит результат так, как будто бы этой ошибки и не было. Или, например, вы вложили ссылку в ссылку, что является неправильным. Что сделает браузер? Увидев открывающую ссылку внутри ссылки, браузер закроет ссылку. Дальше у нас есть еще избыточность: у нас есть закрывающая ссылка без открывающей ссылки. Ну, браузер просто ее проигнорирует, и итоговый результат будет выглядеть как-то так. Кажется, что похожим образом браузер должен вести себя и с формами, но нет. В данном случае браузер просто проигнорирует вложенную форму. А вот что происходит здесь, в данном случае? Я предлагаю вам самим немножечко подумать. Это псевдокод, он, наверное, похож на код, который есть внутри браузера, написанный с использованием какого-то языка, но я думаю, вам несложно понять, что браузер что-то делает, встретив htmlTag и bodyTag. Что же? На самом деле это код, который описывает реакцию браузера на преждевременное употребление закрывающего тега body или закрывающего тега html. Браузер мог бы остановить анализ документа, но нет — браузер просто проигнорирует закрывающие теги body и html и продолжит анализ документа после них. Тот же самый механизм есть и при парсинге CSS. Во-первых, браузер формулирует объектную модель CSS. Выглядит она как-то так. Эта объектная модель позволяет потом наложить этот CSS на html. И внутри парсера CSS также заложен щадящий механизм ошибок. В данном случае у нас есть несколько ошибок. Я предлагаю вам поискать их несколько секунд самим, вы можете замедлить это видео. Итак, я надеюсь, что вы нашли все ошибки. Вот они. Во-первых, нет точки с запятой после правила ширины. Это влияет на следующее правило. Дальше у нас есть несуществующее свойство bem. Здесь у нас также нет закрывающей точки с запятой. В правиле color red у нас пропущено двоеточие, и наконец у нас пропущена закрывающая фигурная скобка, которая влияет на все правило baz. Что будет в браузере в итоге? Вот эти два правила он просто проигнорирует, потому что здесь написан невалидный CSS. Это правило также проигнорирует, потому что здесь используется несуществующая единица измерения. Интереснее браузер поведет себя со свойством font. Это правило абсолютно корректное и валидное и будет обработано браузером таким образом. И, наконец, правило baz также будет проигнорировано, а также будут проигнорированы все правила до конца документа. Что же делать? Винни Пух нам говорит примерно так: «Нужно делать так, как нужно, а как не нужно, делать не нужно!» Наверное, это глупость, и для самопроверки в браузерах можно использовать специальные валидаторы: HTML- и CSS-валидаторы. Они помогут вам избегать ошибок неправильного употребления HTML и CSS. Итак, браузер обработал ваш HTML и CSS, и следующее действие, которое он делает, это сформулирует Render Tree. Я хочу обратить ваше внимание на то, что в терминах браузера Mozilla Firefox Render Tree называется Frame Tree. Но в Интернете и в вебе прижился термин Render Tree, и чаще всего вы будете видеть именно его. Что же происходит? У нас есть DOM, у нас есть CSSOM, и складывая два этих дерева, браузер делает Render Tree. Вы можете легко сопоставить, какие элементы попадают в Render Tree — это те элементы, которые браузер в итоге покажет на странице. Например, у тега span у нас задано CSS-свойство display none. И именно поэтому содержимое внутри тега span не попадет в Render Tree. Также внутрь Render Tree не попадет содержимое тега head, так как это служебная информация, которая необходима браузеру. Как же формируется Render Tree? Оно получается при складывании DOM-дерева и CSSOM-дерева. Не все блоки из DOM-дерева попадут в Render Tree. Как вы видели ранее, например, блоки со свойством CSS hidden не попадут в Render Tree. Также, например, в него не попадут элементы внутри тега head или, например, инпуты с атрибутом type="hidden". На один блок в DOM-дереве может создаваться несколько блоков в Render Tree. Например, для элементов списков у нас создается два элемента: элемент, содержащий текст, и элемент, содержащий bullet. Другой пример вы также могли видеть на предыдущей картинке, когда у нас внутри текста создается несколько Render Tree блоков, так как внутри текста есть еще один элемент. И, наконец, CSS также оказывает влияние на Render Tree и может добавлять ноды в него. За это отвечают такие псевдоэлементы, как after и before, а также атрибут content, который до недавнего времени работал в браузере Opera на движке Presto. В данном видео мы рассмотрели то, как браузер анализирует документы и как получаются DOM и CCSOM, как браузер обрабатывает ошибки HTML и CSS, а также что такое Render Tree и как оно получается.