结尾
从开始学习前端时,就始终有着这么一条规定:CSS 要放在 Head 标签中引入。
但至于为什么要这么做呢?却找不到一个令人感觉称心的答复,因而这篇文章咱们从 性能以及交互方面 来探索一下这个问题。
筹备
Chrome 浏览器的 devtool 配置有 Performance 性能,能够对网页进行性能剖析,并且会将网页解析渲染流程以图形展现进去,这对咱们的剖析有极大的帮忙。
应用办法:鼠标右键 + 查看 or F12,而后切换到Performance 一栏,点击左上角的刷新按钮便能够对页面进行剖析。
如何应用 Performance 工具进行网页剖析
开始探索
先找一个内部的 css 文件:https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/1.4.0/css/bootstrap.css
这是一个 bootstrap.css 的 cdn 文件,别离搁置在 head 标签 中和body 标签尾部:
- 搁置于 head 标签中:
<!doctype html>
<html>
<head>
<title> 钻研精力 </title>
</head>
<body>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/1.4.0/css/bootstrap.css" rel="stylesheet">
<p> 你好, 小枫 </p>
</body>
</html>
(a) 浏览器先进行 HTML 解析工作,生成 DOM 树;
(b) 浏览器调用 Network 线程下载 bootstrap.css 文件,此时 HTML 未进行渲染步骤;等到 css 文件下载结束之后,开始解析 css 款式,生成 CSSOM 树;之后再联合 DOM 树和 CSSOM 树生成 Layout 树(以前称为 Render 树),开始计算布局,进行绘制步骤(生成 Paint 树,细节不探索),出现页面(前面还有一步Composite,这里不作探索)。
从下面的步骤能够看出,当内部 css 在 head 标签中引入时,HTML 的解析步骤失常执行,但渲染步骤会期待 css 文件下载结束并解析胜利之后再进行,所以能够得出结论:
当 css 在 head 标签中引入时,阻塞 HTML 的渲染。
而页面的出现过程应该如下:页面出现一段时间的白屏(白屏工夫取决于 css 文件的下载速度),之后呈现出带有 css 款式的页面 。为了更能直观地出现这个过程,咱们接着应用万能的 Chrome devtool 进行弱网环境的模仿:在Network 中将网络速度设置为Slow 3G。
刷新页面察看页面:
(a) 页面呈现长时间白屏状态:
(b) 一段时间过后,呈现带有 css 款式的文本信息,示意页面渲染结束:
2. 搁置于 body 标签中(这里先放在尾部):
<!doctype html>
<html>
<head>
<title> 钻研精力 </title>
</head>
<body>
<p> 你好, 小枫 </p>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/1.4.0/css/bootstrap.css" rel="stylesheet">
</body>
</html>
(a) 在解析到 link 标签之前,浏览器自上而下解析 HTML 生成 DOM 树,而后与 CSSOM 树(并非内部引入的 CSS)联合生成了 Layout 树,计算布局之后进行绘制,将页面渲染到浏览器中;
(b) 浏览器解析到 link 标签,下载内部 css 文件;下载完之后开始解析 css 款式生成 CSSOM 树,并从新解析 HTML 生成 DOM 树;将 DOM 树和 CSSOM 树联合生成 Layout 树,进行计算布局和 Paint,实现页面的渲染,这个过程称为reflow,也就是回流,是一种耗费性能的景象;
从下面的步骤能够看出,当内部 css 在 body 标签中引入时,不会阻塞 HTML 的渲染,所以页面出现过程应该如下:首先,在 css 加载实现之前,文本先渲染实现,但未带有 css 款式,俗称“裸奔”;css 加载实现之后,页面中文本款式产生扭转;因而会呈现“闪一下”甚至长时间“裸奔”的景象,因为页面款式产生了变动:“裸奔”到“有款式”;如上图,页面存在长时间 Layout shift 景象,这里科普一下Layout shift:
CLS,全称 是CumulativeLayout Shift,中文名 是累计布局偏移,是 Google Search Console 额一个外围网页指标, 是指网页布局在加载期间的偏移量。得分范畴 是0–1,其中 0 示意没有偏移,1 示意最大偏移。
在页面出现之后,款式产生了变动,导致页面布局与原先布局有了偏移,这是一种十分不好的交互体验,这里附上一篇 CLS 的文章:页面视觉稳定性之 CLS,有趣味能够看看。
咱们接着进行 弱网模仿 来更加直观地展现页面的变动:
(a) css 未加载实现前,页面呈现“裸奔”景象:
(b) css 加载实现之后,页面从新渲染,文本款式发生变化(font-size 有显著的变动):
从下面的探索能够晓得:css 在 body 中引入时,不会阻塞页面的渲染;那么会阻塞页面解析吗?咱们接着探索这个问题。
3. 搁置于 body 标签中(这里放在两头):
<!doctype html>
<html>
<head>
<title> 钻研精力 </title>
</head>
<body>
<p> 你好, 小枫 </p>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/1.4.0/css/bootstrap.css" rel="stylesheet">
<p> 你好, 小枫 </p>
</body>
</html>
应用弱网对页面出现过程进行剖析:
(a) css 加载未实现时,页面仅展现第一行文本,并且呈“裸奔”状态;
(b) css 加载结束,页面从新渲染,展现所有文本,并且带有 css 款式;
能够看出,css 在 body 中引入时,阻塞了 HTML 的解析,因而在下载内部 css 文件的过程中,第二行文本信息未能解析渲染进去,所以咱们得出结论:
当 css 在 body 标签中引入时,阻塞 HTML 的解析,但不阻塞 HTML 的渲染。
总结
- css 在 head 标签中引入时,会阻塞 HTML 的渲染 ,因而页面只有等到 css 下载并解析实现之后才会进行渲染,所以最终呈现的页面是 带有残缺款式 的;这个过程只产生一次解析渲染 :_HTML 解析生成 DOM 树 +CSS 解析生成 CSSOM 树 + 联合生成 Layout 树 + 计算布局 + 绘制_;但也存在毛病: 在 css 文件下载比较慢时,会呈现长时间白屏 ,但与呈现“裸奔”页面相比, 白屏仿佛在体验上显得更加敌对。
- css 在 body 标签中引入时,会阻塞 HTML 的解析,但不阻塞 HTML 的渲染 ,因而页面在 css 下载实现之前会将 link 标签前的 HTML 先进行解析渲染,并展示在页面,但因为没有 css 款式,页面会呈现“裸奔”景象;等到 css 下载解析实现之后,页面从新解析渲染,展现出带有款式的 HTML,这个过程会导致reflow 或是 repaint;从用户体验方面看:css 在 body 标签中引入时,尽管页面能够先展示进去,但因为“裸奔”景象,会导致极差的用户体验;从性能方面看,与css 在 head 标签中引入 相比,页面在 css 加载实现后须要 从新解析渲染,这个过程带来了极大的性能损耗。