浏览器渲染原理:
步骤:
- 根据HTML构建HTML树(DOM)
- 根据CSS构建CSS树(CSSOM)
- 将两棵树合并成一颗渲染树(render tree)
- Layout布局(文档流、盒模型、计算大小和位置)
- Paint绘制(把边框颜色、文字颜色、阴影等画出来)
- Compose合成(根据层叠关系展示画面)
具体可参考图:
如果 DOM 或 CSSOM 被修改,只能再执行一遍以上所有步骤,以确定哪些像素需要在屏幕上进行重新渲染。优化关键渲染路径就是指最大限度缩短执行上述第 1 步至第6 步耗费的总时间。当我们更新网页样式或者设置一些动画效果后,网页内容就会发生更新,而三种渲染方式分别是:
- JS / CSS > 样式 > 布局 > 绘制 > 合成
如果修改元素的“layout”属性,也就是改变了元素的几何属性(例如宽度、高度、左侧或顶部位置等),那么浏览器将必须检查所有其他元素,然后“自动重排”页面。任何受影响的部分都需要重新绘制,而且最终绘制的元素需进行合成。
- JS / CSS > 样式 > 绘制 > 合成
如果修改“paint only”属性(例如背景图片、文字颜色或阴影等),即不会影响页面布局的属性,则浏览器会跳过布局,但仍将执行绘制。
- JS / CSS > 样式 > 合成
如果更改一个既不要布局也不要绘制的属性,则浏览器将跳到只执行合成。
至于更改哪些属性会影响布局、绘制、合成,可以参考CSS trigggers
CSS动画的两种做法
transition:
transition作用是补充中间帧,可以为一个元素在不同状态之间切换的时候定义不同的过渡效果。比如在不同的伪元素之间切换,像是 :hover,:active 或者通过 JavaScript 实现的状态变化。
比如如下代码:
img{
height:100px;
width:100px;
}
img:hover{
height: 200px;
width: 200px;
}
当鼠标放置于缩略图之上,缩略图会迅速变大,几乎是瞬间实现的。但是,通过添加transition属性,可以为变化指定所需时间以及过度的方式等。
语法:
- transition: 属性名 时长 过渡方式 延迟,属性名(transition-property),时长(transition-duration),过渡方式(transition-timing-function) 和 延迟(transition-delay)
- transition-property: none | all | IDENT ,相当于指定适用的属性,具体参考MDN: transition-property
- transition-duration:
- transition-timing-function:
,状态的变化速度,默认不是匀速的,而是逐渐放慢,这叫做ease。其他模式还包括linear:匀速,ease-in:加速,ease-out:减速,cubic-bezier函数:自定义速度模式,具体参考MDN: transition-timing-function - transition-delay:
可以为上面的img标签增加transition属性:
img{
transition: 1s 1s all ease;
}
这是简写模式,还可以单独定义各个属性:
img{
transition-property: all;
transition-duration: 1s;
transition-delay: 1s;
transition-timing-function: ease;
}
代码实现的效果就是鼠标放置于缩略图之上,缩略图在延迟1s后以逐渐放慢的速度变大为原来的两倍。
transition的局限:
- transition需要事件触发,所以没法在网页加载时自动发生
- transition是一次性的,不能重复发生,除非一再触发
- transition只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态
- 一条transition规则,只能定义一个属性的变化,不能涉及多个属性
-
animation:
animation用来指定一组或者多组动画,每组之间用逗号分隔。比如:
div:hover {
animation: 1s xxx;
}
代码表示,当鼠标悬停在div元素上时,会产生名为xxx的动画效果,持续时间为1秒。为此,我们还需要用keyframes关键字,定义xxx效果。
@keyframes 规则通过在动画序列中定义关键帧(或waypoints)的样式来控制CSS动画序列中的中间步骤。关键帧的常用写法如下:/*第一种写法*/
@keyframes xxx {
from { background: red; }
to { background: yellow; }
}
或者:
/*第二种写法*/
@keyframes xxx {
0% { background: red; }
100% { background: yellow; }
}
from等效于 0%,to等效于 100%,第二种写法可以用百分数表示触发关键帧的时间点,可以描述更多状态,推荐这种写法。上面代码表示xxx效果一共有两个状态,分别为起始(0%)和结束(100%)。
语法:
animation 属性是 animation-name,animation-duration, animation-timing-function,animation-delay,animation-iteration-count,animation-direction,animation-fill-mode 和 animation-play-state 属性的一个简写属性形式。具体参考MDN: animation
animation-name: none | IDENT,指定应用的一系列动画,每个名称代表一个由@keyframes定义的动画序列。
- animation-duration:
- animation-timing-function:
, 默认值为ease。 - animation-delay:
- animation-iteration-count: infinite |
, 定义动画在结束前运行的次数 可以是1次,也可以是无限循环。 - animation-direction,动画循环播放时,每次都是从结束状态跳回到起始状态,再开始播放。animation-direction属性,可以改变这种行为。默认情况是,animation-direction等于normal。还可以等于取alternate(动画在奇数次正向播放,在偶数次反向播放)、reverse(动画反向播放)、alternate-reverse(动画在奇数次反向播放,在偶数次正向播放)等值。
- animation-fill-mode,动画结束以后,会立即从结束状态跳回到起始状态。如果想让动画保持在结束状态,需要使用该属性。取值为none:默认值,回到动画没开始时的状态,forwards表示让动画停留在结束状态,backwards:让动画回到第一帧的状态,both: 根据animation-direction轮流应用forwards和backwards规则。
- animation-play-state: pauesd | running,定义一个动画是否运行或者暂停。比如:
上面的代码表示,没有鼠标没有悬停时,动画状态是暂停;一旦悬停,动画状态改为继续播放。div {
animation: xxx 1s linear infinite;
animation-play-state: paused;
}
div:hover {
animation-play-state: running;
}
animation属性可以简写,并且各属性次序不重要,具体实现示例可参考跳动的心。