结尾

从开始学习前端时,就始终有着这么一条规定: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标签尾部:

  1. 搁置于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加载实现后须要从新解析渲染,这个过程带来了极大的性能损耗。