浏览器渲染原理
浏览器会使用我们的 HTML、CSS 和 JavaScript 进行渲染,可以简单的将其分成以下几个关键步骤
- 根据HTML构建HTML树(DOM)
- 根据CSS构建CSS数(CSSOM)
- 将两棵树合并成一颗渲染树(render tree)
- Layout布局(文档流、盒模型、计算大小和位置)
- Paint绘制(把边框颜色、文字颜色、阴影等画出来)
- Composite合成(根据层叠关系展示画面)
浏览器渲染页面前需要先构建 DOM 和 CSSOM 树。
文档对象模型 (DOM)
浏览器每次处理 HTML 标记时,都会完成:将字节转换成字符,确定令牌,将令牌转换成节点,然后构建 DOM 树。
- 转换: 浏览器从磁盘或网络读取 HTML 的原始字节,并根据文件的指定编码(例如 UTF-8)将它们转换成各个字符。
- 令牌化: 浏览器将字符串转换成 W3C HTML5 标准规定的各种令牌,例如,“”、“”,以及其他尖括号内的字符串。每个令牌都具有特殊含义和一组规则。
- 词法分析: 发出的令牌转换成定义其属性和规则的“对象”。
- DOM 构建: 最后,由于 HTML 标记定义不同标记之间的关系(一些标记包含在其他标记内),创建的对象链接在一个树数据结构内,此结构也会捕获原始标记中定义的父项-子项关系:HTML 对象是 body 对象的父项,body 是 paragraph 对象的父项,依此类推。
整个流程的最终输出是我们这个简单页面的文档对象模型 (DOM),浏览器对页面进行的所有进一步处理都会用到它。
**
CSS 对象模型 (CSSOM)
与处理 HTML 时一样,需要将收到的 CSS 规则转换成浏览器能够理解和处理的东西。
创建CSS树时,重复 HTML 过程,不过是为 CSS 而不是 HTML:CSS 字节转换成字符,接着转换成令牌和节点,最后链接到一个称为“CSS 对象模型”(CSSOM) 的树结构内;
如果 DOM 或 CSSOM 被修改,您只能再执行一遍以上所有步骤,以确定哪些像素需要在屏幕上进行重新渲染。
**
渲染树构建、布局及绘制
构建渲染树
刚刚我们根据 HTML 和 CSS 输入构建了 DOM 树和 CSSOM 树。 但是,它们都是独立的对象,分别网罗文档不同方面的信息:一个描述内容,另一个则是描述需要对文档应用的样式规则。我们要将CSSOM 树和 DOM 树合并成渲染树。
为构建渲染树,浏览器大体上完成了下列工作:
- 从 DOM 树的根节点开始遍历每个可见节点。
- 某些节点不可见,因为它们不会体现在渲染输出中,所以会被忽略。
- 某些节点通过 CSS 隐藏,因此在渲染树中也会被忽略。
- 对于每个可见节点,为其找到适配的 CSSOM 规则并应用它们。
- 发射可见节点,连同其内容和计算的样式。
有了渲染树,我们就可以进入“布局”阶段。
为弄清每个对象在网页上的确切大小和位置,浏览器会从渲染树的根节点开始进行遍历。
布局流程的输出是一个“盒模型”,它会精确地捕获每个元素在视口内的确切位置和尺寸:所有相对测量值都转换为屏幕上的绝对像素。
“绘制”或“栅格化”
既然我们知道了哪些节点可见、它们的计算样式以及几何信息,我们终于可以将这些信息传递给最后一个阶段:将渲染树中的每个节点转换成屏幕上的实际像素。这一步通常称为“绘制”或“栅格化”。
执行渲染树构建、布局和绘制所需的时间将取决于文档大小、应用的样式,以及运行文档的设备:文档越大,浏览器需要完成的工作就越多;样式越复杂,绘制需要的时间就越长。
**
CSS 动画的两种做法(transition 和 animation)
transition
-
作用
-
语法
transition:属性名 时长 过渡方式 延迟
transition:left 200ms linear 3
可以用逗号分隔两个不同属性
transition:left 200ms , top 400ms
可以用all代表所有属性
transition:all 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是可以过渡的
-
使用两次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
animation: xxx 1.5s forwards;
@keyframes完整语法
标准写法
- 搜索keyframes MDN讲得很清楚
- 一种写法是from to
@keyframes slidein { from { transform: translateX(0%); } to { transform: translateX(100%); } }
另一种写法是百分数(用的更广泛)
@keyframes identifier { 0% { top: 0; left: 0; } 30% { top: 50px; } 68%, 72% { left: 50px; } 100% { top: 100px; left: 100%; } }