CSS3 规范出现之前,要实现一个动画效果那必须借助 JavaScript 的能力才够得着,所以当时的前端开发但凡听到动画交互,那眉头可就成了一个川字儿了~
transition 的出现,改变了实现动画难的困境,也让前端的交互不再生硬,所有的页面元素如同有了灵性一般。
transition 过渡
要实现一个 CSS 属性 0 -> 1
的变化,在不使用 transition 的情况下,元素就两种状态 0
和 1
,而 transition 则是将 0 -> 1 之间的变化完全呈现给了用户,看起来就像是属性 0 慢慢的走到 1,而不是从 0 闪现到 1,期间元素走过了 0.1
0.2
0.3
... 1
,这种变化就叫过渡。
transition 相关的 CSS 属性:
transition-property
指定哪些 CSS 属性需要应用过渡动画transition-duration
定义动画持续时间transition-timing-function
控制动画速度变化曲线transition-delay
设置动画开始前的等待时间,也就是延迟执行transition
简写属性will-change
提前告知浏览器哪些属性会变化(优化性能)
transition-property
transition-property
属性用于告诉浏览器哪个 CSS 属性要用来做过渡效果,可以是单个属性,也可以是多个属性,还可以是关键字 all
。
语法:
css
transition-property: none; /* 无属性过渡 */
transition-property: all; /* 所有属性都添加过渡效果,出于性能考虑不建议使用 all */
transition-property: transform; /* 只对 transform 做过渡 */
transition-property: transform, opacity; /* 只对 transform 和 opacity 添加过渡 */
过渡动画必须几个属性同时设置才会有效,所以单个属性无法演示~
transition-duration
transition-duration
属性用于设置过渡动画的持续时间,单位是秒(s)或毫秒(ms),默认是 0s,表示没有过渡动画。
需注意单位换算关系:1s=1000ms
语法:
css
transition-duration: 0s; /* 无过渡动画 */
transition-duration: 0.5s; /* 所有属性都添加 0.5s 过渡 */
transition-duration: 0.5s, 200ms; /* transition-property 指定的第一个属性持续 0.5s,第二个属性持续 200ms */
transition-timing-function
transition-timing-function 用于设置速度曲线,控制动画速度变化,这里面有个叫做 贝塞尔曲线
的东东,顶级大佬做出来的都是一堆数学公式~~本文不会介绍如何绘制贝塞尔曲线,咱们学会怎么使用即可,如果对贝塞尔曲线绘制感兴趣可查找相关书籍。
相关属性值:
-
ease
默认值,在过渡的中间增加速度,在过渡结束时减慢速度。等于cubic-bezier(0.25, 0.1, 0.25, 1.0)
-
linear
以均匀的速度过渡。等于cubic-bezier(0.0, 0.0, 1.0, 1.0)
-
ease-in
开始缓慢,过渡速度逐渐增加,直到完成。等于cubic-bezier(0.42, 0, 1.0, 1.0)
-
ease-out
开始快速过渡,随着过渡的继续而减慢。等于cubic-bezier(0, 0, 0.58, 1.0)
-
ease-in-out
开始缓慢过渡,然后加速,然后再次减速。等于cubic-bezier(0.42, 0, 0.58, 1.0)
-
cubic-bezier(x1, y1, x2, y2)
自定义贝塞尔曲线,x1, y1
和x2, y2
分别代表曲线控制点坐标,其中 x1 和 x2 值必须在 0 到 1 的范围内。 -
step-start
等于steps(1, jump-start)
-
step-end
等于steps(1, jump-end)
-
steps(n, <jump-term>)
在过渡过程中显示n个停留点,每个停留点显示的时间长度相等。例如:如果 n 是 5,那么就有 5 个步骤。过渡过程是在 0%、20%、40%、60% 和 80% 处暂时停留,还是在 20%、40%、60%、80% 和 100% 处停留,或者是在 0% 到 100% 之间设置5个停留点,亦或是包括0%和100%标记在内的5个停留点(在0%、25%、50%、75%和100%处),这取决于使用以下哪个
<jump-term>
:jump-start
表示左连续函数,即第一个跳跃发生在过渡开始时;
jump-end
表示右连续函数,即最后一个跳跃发生在动画结束时;
jump-none
两端都没有跳跃。相反,在0%和100%标记处各自停留,每个停留点占持续时间的1/n;
jump-both
在 0% 和 100% 标记处都包含暂停,实际上在过渡时间内增加了一个步骤;
start
与 jump-start 相同。
end
与 jump-end 相同。
语言很空洞,看后面例子。
语法:
css
transition-timing-function: ease;
transition-timing-function: linear;
transition-timing-function: cubic-bezier(0.1, 0.7, 1, 0.1);
transition-timing-function: step-start;
transition-timing-function: steps(5, jump-end);
在使用 Chrome 调试工具时候,发现 linear
还有一种函数式的写法,查阅了兼容性,发现这种写法比较吃浏览器版本,都是 2023 年之后的浏览器版本才开始支持。写法如下:
css
/* 第一位表示运动进度,第二位表示时间百分比 */
transition-timing-function: linear(
0 0%,
0.22 2.1%,
0.86 6.5%,
1.11 8.6%,
1.3 10.7%,
1.35 11.8%,
1.37 12.9%,
1.37 13.7%,
1.36 14.5%,
1.32 16.2%,
1.03 21.8%,
0.94 24%,
0.89 25.9%,
0.88 26.85%,
0.87 27.8%,
0.87 29.25%,
0.88 30.7%,
0.91 32.4%,
0.98 36.4%,
1.01 38.3%,
1.04 40.5%,
1.05 42.7%,
1.05 44.1%,
1.04 45.7%,
1 53.3%,
0.99 55.4%,
0.98 57.5%,
0.99 60.7%,
1 68.1%,
1.01 72.2%,
1 86.7%,
1 100%
)
transition-delay
transition-delay
属性用于设置过渡动画开始前的等待时间,单位是秒(s)或毫秒(ms),默认是 0s,表示不用延迟。语法与 transition-duration 一样。
transition
简写属性,同时设置 transition-property
、transition-duration
、transition-timing-function
、transition-delay
四个属性。
语法:
css
transition: transform 3s; /* transform 属性添加 3s 过渡 */
transition: transform 3s 0.5s; /* transform 属性添加 3s 过渡,延迟 0.5s 开始 */
transition: transform 3s ease-in-out; /* transform 属性添加 3s 过渡,使用 ease-in-out 速度曲线 */
transition: transform 3s ease-in-out 0.5s; /* transform 属性添加 3s 过渡,使用 ease-in-out 速度曲线,延迟 0.5s 开始 */
will-change
will-change 这是一般双刃剑,用得好可以优化性能,用得不好反而会使用大量机器资源导致页面变慢!!
使用准则:此属性应当作为最后的手段使用,不要过早优化,如果您的页面未出现卡顿变慢,那么您不需要使用这个属性!
使用方式:
css
will-change: transform; /* 提前分配 GPU 资源,优化 transform 变化 */
效果演示
不同曲线效果
不同曲线会影响动画运动速度。
html
<div class="box">
<div class="child">ease</div>
<div class="child">linear</div>
<div class="child">ease-in</div>
<div class="child">ease-out</div>
<div class="child">ease-in-out</div>
<div class="child">cubic-bezier</div>
</div>
<style>
.box {
border: 2px solid rgba(255, 71, 87,0.3);
margin: 20px 0;
width: calc(235px * 3);
/* height: calc(100px * 3); */
}
.child {
border: 2px solid rgba(255, 71, 87,1);
border-radius: 40px;
width: 100px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
transition-duration: 2s;
transition-property: transform;
}
.child:nth-child(1) {
transition-timing-function: ease;
}
.child:nth-child(2) {
transition-timing-function: linear;
}
.child:nth-child(3) {
transition-timing-function: ease-in;
}
.child:nth-child(4) {
transition-timing-function: ease-out;
}
.child:nth-child(5) {
transition-timing-function: ease-in-out;
}
.child:nth-child(6) {
transition-timing-function: cubic-bezier(0, 1.59, .83, .67);
}
.box:hover .child {
/* 鼠标放在box上时,子元素向右移动605px */
transform: translateX(605px);
}
</style>
效果:

steps 逐帧动画效果
steps 可以理解为关键帧动画,每次都跳到一个关键帧。
html
<div class="box">
<div class="child">step-start</div>
<div class="child">step-end</div>
<div class="child">steps(5, start)</div>
<div class="child">steps(5, jump-start)</div>
<div class="child">steps(5, jump-end)</div>
<div class="child">steps(5, jump-none)</div>
<div class="child">steps(5, jump-both)</div>
<div class="child">steps(5, start)</div>
<div class="child">steps(5, end)</div>
</div>
<style>
.box {
border: 2px solid rgba(255, 71, 87,0.3);
margin: 20px 0;
width: calc(235px * 3);
}
.child {
border: 2px solid rgba(255, 71, 87,1);
border-radius: 40px;
width: 170px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
transition-duration: 2s;
transition-property: transform;
}
.child:nth-child(1) {
transition-timing-function: step-start;
}
.child:nth-child(2) {
transition-timing-function: step-end;
}
.child:nth-child(3) {
transition-timing-function: steps(5, start);
}
.child:nth-child(4) {
transition-timing-function: steps(5, jump-start);
}
.child:nth-child(5) {
transition-timing-function: steps(5, jump-end);
}
.child:nth-child(6) {
transition-timing-function: steps(5, jump-none);
}
.child:nth-child(7) {
transition-timing-function: steps(5, jump-both);
}
.child:nth-child(8) {
transition-timing-function: steps(5, start);
}
.child:nth-child(9) {
transition-timing-function: steps(5, end);
}
.box:hover .child {
/* 鼠标放在box上时,子元素向右移动535px */
transform: translateX(535px);
}
</style>
效果:

不同持续时间
持续时间越短,运动越快。
html
<div class="box">
<div class="child">1s</div>
<div class="child">2s</div>
<div class="child">500ms</div>
<div class="child">1500ms</div>
</div>
<style>
.box {
border: 2px solid rgba(255, 71, 87,0.3);
margin: 20px 0;
width: calc(235px * 3);
}
.child {
border: 2px solid rgba(255, 71, 87,1);
border-radius: 40px;
width: 100px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
transition-property: transform;
}
.child:nth-child(1) {
transition-duration: 1s;
}
.child:nth-child(2) {
transition-duration: 2s;
}
.child:nth-child(3) {
transition-duration: 500ms;
}
.child:nth-child(4) {
transition-duration: 1500ms;
}
.box:hover .child {
/* 鼠标放在box上时,子元素向右移动605px */
transform: translateX(605px);
}
</style>
效果:

不同延迟时间
延迟时间越长,动画等待时间越久。
html
<div class="box">
<div class="child">1s</div>
<div class="child">2s</div>
<div class="child">500ms</div>
<div class="child">1500ms</div>
</div>
<style>
.box {
border: 2px solid rgba(255, 71, 87,0.3);
margin: 20px 0;
width: calc(235px * 3);
}
.child {
border: 2px solid rgba(255, 71, 87,1);
border-radius: 40px;
width: 100px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
transition-duration: 2s;
transition-property: transform;
}
.child:nth-child(1) {
transition-delay: 1s;
}
.child:nth-child(2) {
transition-delay: 2s;
}
.child:nth-child(3) {
transition-delay: 500ms;
}
.child:nth-child(4) {
transition-delay: 1500ms;
}
.box:hover .child {
/* 鼠标放在box上时,子元素向右移动605px */
transform: translateX(605px);
}
</style>
效果:

贝塞尔曲线
Chrome 开发者工具内置曲线调试工具:

点击 1
可以呼出调试工具,2
可以切换不同类型的曲线,3
可以切换同类型的不同曲线,4
可以拖拽手柄绘制不同曲线。
这里再分享一个在线绘制贝塞尔曲线的链接:https://yisibl.github.io/cubic-bezier/
图解贝塞尔曲线:

图中红色箭头指向的红点表示:在动画执行 37% 时间的时候要运动到目标的 53% 位置。
图中 1(x1, y1) 和 2(x2, y2) 分别表示控制贝塞尔取消的两个坐标点,cubic-bezier(x1, y1, x2, y2)。
贝塞尔曲线越陡峭,表示速度越快。
总结
- 在使用 transition 过渡动画时,必须要有触发条件!比如鼠标放上时、鼠标离开时、元素的 class 变化等。
- transition 无法做到让元素无休止的运动下去,过渡动画必须有持续时间!
- transition-property 应当尽可能少的使用
all
(浏览器需要监控元素的所有可过渡属性)。 - transition-property 指定的属性必须是可量化的属性,比如 transform、background-color、color 等,不能是 display、float、font-style 这种无法计算的属性。
- 避免过渡 margin/width 等布局属性(易引发重排,性能差)