浏览器渲染原理
步骤
- 根据 HTML 构建 HTML 树(DOM)
- 根据 CSS 构建 CSS 树(CSSOM)
- 将两棵树合并成一颗渲染树(render tree)
- Layout 布局(文档流,盒模型,计算大小和位置)
- Panit 绘制(把边框颜色,文字颜色,阴影等画出来)
- Composite 合成(根据层叠关系展示画面)
HTML树,CSS树 和 渲染树(render tree)如图:
这些步骤做完了,就展现在我们眼前了。
在更新样式的时候,会省略 Layout 或 Paint 这些步骤,可以通过 Chrome 中的开发者工具里的 Rendering 中添加 Paint flashing。通过高亮显示来突显重绘区域。
更新样式
一般通过 js 来更新样式
如: div.style.background='red'
如: div.style.display='none'
如: div.classList.add('red')
如: div.remove()
有三种更新方式
- 第一种,全走
JS/CSS > 样式 > 布局 > 绘制 > 合成
div.remove()会触发当前消失,其他元素 relayout
- 第二种,跳过 布局(layout)
JS/CSS > 样式 > 绘制 > 合成
改变背景颜色,直接 repaint + composite
- 第三种,跳过 布局(layout) 和 绘制(paint)
JS/CSS > 样式 > 合成
改变 transform,只需 composite
每个属性在不同浏览器都会触发不同的流程,还好这个网站csstriggers.com, 已经把所有属性试过了。
transform 四个常用功能(查看MDN)
- translate 位移
- scale 缩放
- rotate 旋转
- skew 倾斜
#demo{
margin: 100px;
border: 1px solid red;
width: 100px;
height: 100px;
transition: all 1s;
}
#demo:hover{
transform: translateY(100%) rotate(45deg) scale(2) skew(20deg);
}
效果如下:当鼠标放在红色方框内,从图一变成图二,点击查看代码
这些功能一般都需要配合 transition 过渡,inline 元素不支持 transform,需要先变成 block
CSS 动画的两种做法(transition 和 animation)
1. transition 过渡(查看MDN)
作用:补充中间帧
语法(transition: 属性名|时长|过渡方式|延迟 )
- 属性名:动画的名字
- 时长 :1s 或者 1000ms,0.1s 或者 .1s
- 过渡方式:ease | ease-in | ease-out | ease-in-out | cubic-bezier | step-start | step-end | steps
- 延迟:3s 或者 3000ms,0.3s 或者 .3s
/*transition: 属性名 时长 过渡方式 延迟*/
transition: left 1s linear 3s
过渡必须要有起始,一般只有一次动画,或者两次,比如 hover 和 非 hover 状态的过渡
2. animation (查看MDN)
语法(animation:时长|过渡方式|延迟|次数|方向|填充模式|是否暂停|动画名)
- 时长:1s 或者 1000ms
- 过渡方式:跟 transition 取值一样,如 linear
- 次数:3 或者 2.4 或者 infinite
- 方向:reverse | alternate | alternate-serverse
- 填充模式:none | forwards | backwards | both
- 是否暂停:paused | running
3.keyframes 完整语法
@keyframes name{
from {
transform: translateX(0%);
}
to {
transform: translateX(100%);
}
}
@keyframes name{
0% {transform: translateX(0%);}
50% {transform: translateX(50%);}
100% {transform: translateX(100%);}
}
用 transition 和 animation ,如果除了起始,还有中间点,怎么办?
.a === transform ===> .b //从 状态a 到 状态b,再从 状态b到 状态c,
.b === transform ===> .c //注意 状态c 的过程,包括先从 状态a 到 状态b!
- 如下图,使用两次 transform,点击查看代码
- 如下图,使用 animation,点击查看代码
如果想让动画停在最后一帧,加上 forwards,否则动画会归位
#demo.start{
animation: xxx 1.5s forwards;
}