乐趣区

关于css:探究-为什么CSS要在head标签中引入

结尾

从开始学习前端时,就始终有着这么一条规定: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 加载实现后须要 从新解析渲染,这个过程带来了极大的性能损耗。
退出移动版