html 页面渲染过程

简述 html 页面渲染过程

整个渲染过程其实就是将 URL 对应的各种资源,通过浏览器渲染引擎的解析,输出可视化的图像。

基本概念

  • HTML 解释器:解释 HTML 语言的解释器,本质是将 HTML 文本解释成 DOM 树(文档对象模型)。

  • CSS 解释器:解释样式表的解释器,其作用是将 DOM 中的各个元素对象加上样式信息,从而你为计算最后结果的布局提供依据。

  • 布局:将 DOM 和 css 样式信息结合起来,计算它们的大小位置等布局信息,形成一个能够标识这所有信息的内部标识模型即渲染树。

  • JavaScript 引擎:JavaScript 可以修改网页的内容,也能修改 CSS 的信息,JavaScript 引擎解释 JavaScript 代码并把代码的逻辑和对 DOM 和 CSS 的改动信息应用到布局中去,从而改变渲染的结果。

基本过程

  1. 解析 HTML 文件,创建 DOM 树

浏览器解析 html 代码,然后创建一个 DOM 树。并行请求 css/image/js 在 DOM 树中,每一个 HTML 标签都有一个对应的结点,并且每一个文本也都会有一个对应的文本节点。DOM 树的根节点就是 documentELement,对应的是 html 标签。

  1. 解析 CSS,形成 CSS 对象模型

浏览器解析 CSS 代码,计算出最终的样式数据。构建 CSSOM 树。对 CSS 代码中非法的羽凡它会直接忽略掉。解析 CSS 的时候会按照如下顺序来定义优先级:

浏览器默认设置 < 用户设置 < 外联样式 < 内联样式 < html 中的 style

  1. 将 CSS 与 DOM 合并,构建渲染树(rendering tree)

DOM Tree + CSSOM -> 渲染树(rendering tree)。渲染树和 DOM 树有点像,但是是有区别的。DOM 树完全和 html 标签一一对应,但是渲染树会忽略掉不需要渲染的元素,比如 head、display:none 的元素等。而且一大段文本中的每一个行在渲染树中都是独立的一个节点。渲染树中的每个节点都存储有对应的 css 属性。

  1. 布局和绘制

一旦渲染树创建好了,浏览器就可以根据渲染树直接把页面绘制到屏幕上。

以上四个步骤并不是一次性顺序完成的。如果 DOM 或者 CSSOM 被修改,以上过程会被重复执行。实际上,CSS 和 JavaScript 往往会多次修改 DOM 或者 CSSOM。

Repaint(重绘)

重绘是改变不影响元素在网页中的位置的元素样式时,譬如 background-color(背景色),border-color(边框色),visibility(可见性),浏览器会根据元素的新属性重新绘制一次(这就是重绘,或者说重新构造样式),使元素呈现新的外观。

重绘不会带来重新布局,所以并不一定伴随重排。

Reflow(重排)

渲染对象在创建完成并添加到渲染树时,并不包含位置和大小信息。计算这些值的过程称为布局或重排。

“重绘” 不一定需要 “重排”,比如改变某个网页元素的颜色,就只会触发 “重绘”,不会触发 “重排”,因为布局没有改变。

但是,“重排” 必然导致 “重绘”,比如改变一个网页元素的位置,就会同时触发 “重排” 和 “重绘”,因为布局改变了。

引申问题:浏览器如何优化渲染?

  • 将多次改变样式属性的操作合并成一次操作

  • 将需要多次重排的元素,position 属性设为 absolute 或 fixed,这样此元素就脱离了文档流,它的变化不会影响到其他元素。例如有动画效果的元素就最好设置为绝对定位。

  • 由于 display 属性为 none 的元素不在渲染树中,对隐藏的元素操作不会引发其他元素的重排。如果要对一个元素进行复杂的操作时,可以先隐藏它,操作完成后再显示。这样只在隐藏和显示时触发 2 次重排。

html 和 css 中的图片加载与渲染规则是什么样的?

Web 浏览器会先把获取到的 HTML 代码解析成一个 DOM 树,HTML 中的每个标签都是 DOM 树中的一个节点,包括 display:none 隐藏的标签,还有 JavaScript 动态添加的元素等。浏览器会获取到所有样式,并会把所有样式解析成样式规则,在解析的过程中会去掉浏览器不能识别的样式。

浏览器将会把 DOM 树和样式规则组合在一起(DOM 元素和样式规则匹配)后将会合建一个渲染树(Render Tree),渲染树类似于 DOM 树,但两者区别还是很大的:渲染树能识别样式,渲染树中每个节点(NODE)都有自己的样式,而且渲染树不包含隐藏的结点(比如 display:none 的节点,还有 head 内的一些节点),因为这些节点不会用于渲染,也不会影响节点的渲染,因此不会包含到渲染树中。一旦渲染树构建完毕后,浏览器就可以根据渲染树来绘制页面了。

简单的归纳就是浏览器渲染 Web 页面大约会经过六个过程:

  • 解析 HTML,构成 DOM 树

  • 解析加载的样式,构建样式规则树

  • 加载 JavaScript,执行 JavaScript 代码

  • DOM 树和样式规则树进行匹配,构成渲染树

  • 计算元素位置进行页面布局

  • 绘制页面,最终在浏览器中呈现

是不是会感觉这个和我们图像加载渲染没啥关系一样,事实并非如此,因为 img、picture 或者 background-image 都是 DOM 树或样式规则中的一部分,那么咱们套用进来,图片加载和渲染的时机有可能是下面这样:

  • 解析 HTML 时,如果遇到 img 或 picture 标签,将会加载图片

  • 解析加载样式,遇到 background-image 时,并不会加载图片,而会构建样式规则树

  • 加载 JavaScript,执行 JavaScript 代码,如果代码中有创建 img 元素之类,会添加到 DOM 树中;如有添加 background-image 规则,将会添加到样式规则树中

  • DOM 树和样式规则匹配时构建渲染树,如果 DOM 树节点匹配到样式规则中的 background-image,则会加载背景图片

  • 计算元素(图片)位置进行布局

  • 开始渲染图片,浏览器将呈现渲染出来的图片

上面套用浏览器渲染页面的机制,但图片加载与渲染还有一定的规则。因为页面中不是所有的 img(或 picture)元素引入的图片和 background-image 引入的背景图片都会加载的。那么就引发出新的问题了,什么时候会真正的加载,加载规则又是什么?

先概括一点:

Web 页面不是所有的图片都会加载和渲染!

根据前面介绍的浏览器加载和渲染机制,我们可以归纳为:

  • 设置 background-image 的元素遇到 display:none 时,图片会加载但不会渲染

  • 设置 background-image 的元素祖先元素设置 display:none 时,background-image 不会渲染也不会加载,而 img 和 picture 引入的图片不会渲染但会加载

  • background-image 引入相同路径相同图片文件名时,图片只会加载一次

  • 样式文件名中 background-image 引入的图片,如果匹配不到 DOM 元素,图片不会加载

  • 伪类引入的 background-image,比如 :hover,只有当伪类被触发时,图片才会加载

你可能感兴趣的:(HTML,html)