浏览器渲染原理

浏览器会使用我们的 HTML、CSS 和 JavaScript 进行渲染,可以简单的将其分成以下几个关键步骤

  • 根据HTML构建HTML树(DOM)
  • 根据CSS构建CSS数(CSSOM)
  • 将两棵树合并成一颗渲染树(render tree)
  • Layout布局(文档流、盒模型、计算大小和位置)
  • Paint绘制(把边框颜色、文字颜色、阴影等画出来)
  • Composite合成(根据层叠关系展示画面)

浏览器渲染页面前需要先构建 DOM 和 CSSOM 树。

文档对象模型 (DOM)

浏览器每次处理 HTML 标记时,都会完成:将字节转换成字符,确定令牌,将令牌转换成节点,然后构建 DOM 树。

  1. 转换: 浏览器从磁盘或网络读取 HTML 的原始字节,并根据文件的指定编码(例如 UTF-8)将它们转换成各个字符。
  2. 令牌化: 浏览器将字符串转换成 W3C HTML5 标准规定的各种令牌,例如,“”、“”,以及其他尖括号内的字符串。每个令牌都具有特殊含义和一组规则。
  3. 词法分析: 发出的令牌转换成定义其属性和规则的“对象”。
  4. DOM 构建: 最后,由于 HTML 标记定义不同标记之间的关系(一些标记包含在其他标记内),创建的对象链接在一个树数据结构内,此结构也会捕获原始标记中定义的父项-子项关系:HTML 对象是 body 对象的父项,bodyparagraph 对象的父项,依此类推。

image.png
整个流程的最终输出是我们这个简单页面的文档对象模型 (DOM),浏览器对页面进行的所有进一步处理都会用到它。
**

CSS 对象模型 (CSSOM)

与处理 HTML 时一样,需要将收到的 CSS 规则转换成浏览器能够理解和处理的东西。

创建CSS树时,重复 HTML 过程,不过是为 CSS 而不是 HTML:CSS 字节转换成字符,接着转换成令牌和节点,最后链接到一个称为“CSS 对象模型”(CSSOM) 的树结构内;
image.png
如果 DOM 或 CSSOM 被修改,您只能再执行一遍以上所有步骤,以确定哪些像素需要在屏幕上进行重新渲染。
**

渲染树构建、布局及绘制

构建渲染树

刚刚我们根据 HTML 和 CSS 输入构建了 DOM 树和 CSSOM 树。 但是,它们都是独立的对象,分别网罗文档不同方面的信息:一个描述内容,另一个则是描述需要对文档应用的样式规则。我们要将CSSOM 树和 DOM 树合并成渲染树。

为构建渲染树,浏览器大体上完成了下列工作:

  1. 从 DOM 树的根节点开始遍历每个可见节点。
    • 某些节点不可见,因为它们不会体现在渲染输出中,所以会被忽略。
    • 某些节点通过 CSS 隐藏,因此在渲染树中也会被忽略。
  2. 对于每个可见节点,为其找到适配的 CSSOM 规则并应用它们。
  3. 发射可见节点,连同其内容和计算的样式。

image.png

有了渲染树,我们就可以进入“布局”阶段。

为弄清每个对象在网页上的确切大小和位置,浏览器会从渲染树的根节点开始进行遍历。
布局流程的输出是一个“盒模型”,它会精确地捕获每个元素在视口内的确切位置和尺寸:所有相对测量值都转换为屏幕上的绝对像素。

“绘制”或“栅格化”

既然我们知道了哪些节点可见、它们的计算样式以及几何信息,我们终于可以将这些信息传递给最后一个阶段:将渲染树中的每个节点转换成屏幕上的实际像素。这一步通常称为“绘制”或“栅格化”。

执行渲染树构建、布局和绘制所需的时间将取决于文档大小、应用的样式,以及运行文档的设备:文档越大,浏览器需要完成的工作就越多;样式越复杂,绘制需要的时间就越长。
**


CSS 动画的两种做法(transition 和 animation)

transition

  • 过渡

    作用

  • 补充中间帧

    语法

    transition:属性名 时长 过渡方式 延迟

    1. transitionleft 200ms linear 3

    可以用逗号分隔两个不同属性

    1. transitionleft 200ms , top 400ms

    可以用all代表所有属性

    1. transitionall 200ms

    过渡方式有:linear | ease | ease-in | ease-out | ease-in-out | cubic-bezier | step-start | step-end | steps
    具体含义

    并不是所有属性都能过渡

  • display:none=>block 没法过渡

  • 一般改成visibility:hidden=>visible
  • display和visibility的区别
  • background是可以过渡的
  • opacity透明的可以过渡

    使用两次transform可以让动画不止有起始点

    先让它从状态a变到状态b,再从状态b变到状态c

  • .a===transform===>.b

  • .b===transform===>.c
  • 如何知道中间点:用setTimeont或者监听transitionend事件

animation

  • 声明关键帧 @keyframes
  • 添加动画

    缩写语法

    animation:时长 | 过渡方式 | 延迟 | 次数 | 方向 | 填充方式 | 是否暂停 | 动画名

  • 时长:1s 或者1000ms

  • 过渡方式:跟transition取值一样,如linear
  • 次数:3或者2.4或者infinite
  • 方向:reverse | alternate | alternate-reverse
  • 填充模式:none | forwards | backwards | both
  • 是否停止:paused | running
  • 以上所有属性都有对应的单独属性

    如何让动画停在最后一帧

  • 搜索css animation stop at end

  • 加个forwards
    1. animation: xxx 1.5s forwards;

@keyframes完整语法

标准写法

  • 搜索keyframes MDN讲得很清楚
  • 一种写法是from to
    1. @keyframes slidein { from { transform: translateX(0%); } to { transform: translateX(100%); } }

另一种写法是百分数(用的更广泛)

  1. @keyframes identifier { 0% { top: 0; left: 0; } 30% { top: 50px; } 68%, 72% { left: 50px; } 100% { top: 100px; left: 100%; } }

参考资料

关键渲染路径
transition
animation