过渡其实很好理解,以下以一个效果来演示:
html
<!DOCTYPE html>
<html lang="cmn-hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.test {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
.item {
height: 100px;
width: 100px;
background-color: red;
}
.item:hover {
background-color: green;
height: 120px;
width: 120px;
}
</style>
</head>
<body>
<div class="test">
<div class="item">
</div>
</div>
</body>
</html>读者可以先自行分析以下以上代码的效果,效果如下:

当我鼠标悬浮的时候,这个盒子会变大,并且颜色会发生改变,这里改变得非常突兀,一移动上去立马就改变了,如果我要让它变化柔和一点,就可以使用过渡来实现,即 transition 属性。
当我们给 .item 添加上 transition: all 1s; 之后,效果如下:

此时就有一个过渡动画了,过渡起来就没有那么突兀了。这里也就引出了过渡的作用,过渡就是给状态的变化添加一些过渡的动画效果。
transition 是四个值的简写属性,分别是 transition-property、transition-duration、transition-timing-function 和 transition-delay,以下一个一个介绍。
transition-property,就是要监听的 CSS 属性,填入 CSS 属性名即可,监听某个属性之后,该属性发生变化的时候就会自动添加过渡动画。可以监听多个 CSS 属性,使用逗号隔开。通常情况下我们都是监听所有 CSS 属性的变化,即使用 all 关键字。默认也是 all 关键字。
并不是所有属性都支持过渡,一般支持过渡的都是数值属性,例如长度,颜色这种。MDN 中每一个元素都有一个
Animation type,这个条目就显示了其是否支持动画。
transition-duration 属性是设置过渡动画完成的时间,我们可以用以下例子来理解上面的两个属性。
css
.test{
transition-duration:2s;
transition-property:width,height;
}以上 CSS,当 .test 的 width 和 height 属性发生变化的时候,盒子的宽高会变化,此时就会自动添加过渡动画,并且过渡动画会在 2 秒钟完成。
transition-timing-function 属性指定是运动状态,比如可以匀速变化,可以先快后慢,可以先慢后快。具体取值可以参考 <easing-function> - CSS:层叠样式表 | MDN
此属性取值的简明版本:
- linear:线性过渡。等同于贝塞尔曲线 (0.0, 0.0, 1.0, 1.0)
- ease:平滑过渡。等同于贝塞尔曲线 (0.25, 0.1, 0.25, 1.0)
- ease-in:由慢到快。等同于贝塞尔曲线 (0.42, 0, 1.0, 1.0)
- ease-out:由快到慢。等同于贝塞尔曲线 (0, 0, 0.58, 1.0)
- ease-in-out:由慢到快再到慢。等同于贝塞尔曲线 (0.42, 0, 0.58, 1.0)
- step-start:等同于 steps (1, start)
- step-end:等同于 steps (1, end)
- steps (<integer>, [ start | end ]?):接受两个参数的步进函数。第一个参数必须为正整数,指定函数的步数。第二个参数取值可以是 start 或 end,指定每一步的值发生变化的时间点。第二个参数是可选的,默认值为 end。
- cubic-bezier (<number>, <number>,<number>, <number>): 特定的贝塞尔曲线类型,4 个数值需在 [0, 1] 区间内
从上面的简明版本可以看到,每一个取值都对应一个贝赛尔曲线(cubic-bezier)或者 step,关于贝塞尔曲线,可以参考 13.贝赛尔曲线,关于 step,可以参考 15.step
绝大多数情况下,我们并不会自定义动画,这里给我们提供的这些关键字动画已经足够我们使用,例如
linear,例如ease,例如ease-in这些,已经很漂亮了。
transition-delay 设置过渡延迟,有时候我们并不希望它立刻开始改变,我希望它过一会儿再改变,这个时候,就得用 transition-delay,类似于 JS 中的 setTimeout()。
transition-delay可以设置为负数,那么就会提前开始改变,例如我设置了 10 秒的过渡效果,并且transition-delay:-3s,那么发生改变的时候,会立刻变到 3 秒钟时刻的效果,然后后面 7 秒执行过渡,相当于动画 3秒钟之前就已经开始了,只是目前才看到效果。
一般来说我们直接使用 transition 属性即可,第一个填 transition-property,第二个填 transition-duration,第三个填 transition-timing-function,第四个填 transition-delay
html
<!DOCTYPE html>
<html lang="cmn-hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.test {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
.item {
height: 100px;
width: 100px;
background-color: red;
transition:
width 1s linear 0.5s,
height 1s linear 0.5s;
}
.item:hover {
background-color: green;
height: 120px;
width: 120px;
}
</style>
</head>
<body>
<div class="test">
<div class="item">
</div>
</div>
</body>
</html>效果如下:

我只监听了 width 和 height 属性,所以颜色变化并不会过渡,这两个属性的变化均会持续一秒,并且均会延迟 0.5 秒才执行,变化以线性运动进行,也就是匀速运动。
如果使用简写写法,要监听多个属性,不能写成
height,height 1s linear 0.5s;,要分开写成多个过渡,如上例所示。
接下来介绍一下 transition 对应的一些事件,首先来回忆一下我们如何用 JS 去实现动画函数,很简单,使用定时器,每隔几毫秒变化一次,就实现了动画效果,当然,如果读者实现过动画函数,就会明白,我们经常会在动画进行到一个阶段的时候做一些事,比如动画开始的时候输出一个动画开始的时候弹一个消息,动画结束之后删除 DOM 元素,这都是很常见的需求,在 JS 动画函数中,对于这种异步需求,我们经常会使用回调函数的模式来完成这个需求。
在 CSS 动画中,不管是 transition 还是 animation,我们也面临着同样的需求,就是动画在某个特定的时间去执行某个特别的事件,但是由于这些动画是 CSS 中添加的,并不是在 JS 中调用某个函数来实现的,所以我们无法通过回调函数的模式来解决这个异步场景。为了实现这样的需求,JS 添加了几个事件,CSS 通过在监听过渡和动画的不同阶段来触发相应事件的方式完成了这个异步场景。
关于 transition,JS 中有四个事件供使用
- transitionrun
- transitionstart
- transtionend
- transitioncancel
当一个 DOM 元素发生过渡动画的时候,会在过渡的特定时间点触发对应的事件,这里介绍这四个事件具体在什么时间点被触发:
- transitionrun: 过渡创建的时候触发该事件
- transitionstart: 过渡开始的时候触发该事件
- transitionend: 过渡结束的时候触发该事件
- transitioncancel: 过渡被取消的时候触发该事件
我们可以认为 transitionrun 就是过渡创建的时候被触发,这一定是第一个触发的事件,而 transitionstart 是过渡开始的时候才被触发,这二者是不同的,比如一个过渡动画延迟两秒钟之后开始,那么 transitionstart 也就会延迟两秒钟触发,而 transitionrun 是在一开始过渡创建的时候就已经被触发了。剩下两个非常好理解,这里不进一步赘述。