始发于我的博客 ryougifujino.com。
CSS transitions 提供了一种在改变CSS属性时控制动画速度的方法。你可以让某个属性在一段时间里逐渐改变,而不是猛地突变。例如,如果你想把颜色从白色变为黑色,通常这个变化是突然地。而利用CSS transitions,这个变化可以发生在一段时间里,并且遵循一个加速曲线,所有的这一切都是可定制的。
涉及在两个状态之间过渡的动画被称为隐式过渡( implicit transitions),因为在开始和结束状态之间的状态是由浏览器隐式定义的。
CSS transitions 让你自行决定对哪些属性产生动画(通过显式地把它们列出来),动画何时发生(通过设置delay),过渡持续多久(通过设置duration),和过渡如何执行(通过定义一个timing function,例如,线性的或者先快后慢的)。
哪些 CSS 属性可以被过渡?
网页作者可以定义哪些属性需要执行和以何种方式执行动画。这可以创建非常复杂的过渡。由于某些属性执行动画是没有意义的,所以可执行动画的属性被限制在了一个有限集之中。
注意:可执行动画的属性会随着规范的发展而变化。
auto
这个值通常来说是非常复杂的。规范推荐在定义动画时,不要在开始(from)和结束(to)中使用auto
。(The specification recommends not animating from and to auto.)一些基于Gecko的UA,现实了这个需求,而另一些基于WebKit的UA则没有很严格地实现。所以在动画里使用auto
可能会导致不可预测的结果,根据浏览器和它们的版本而定,这种情况应该被避免。
定义 transitions
CSS Transitions 是由简写属性transition
所控制的。这是配置过渡的最佳方式,因为这样的方式可以更容易地避免参数上的不同步(这种不同步会很让人泄气,并且不得不花大量的时间在CSS里debug)。
你可以使用以下子属性来控制过渡的各个部分:
(注意这些无限循环的过渡只是出于举例的目的;这些CSS transition
只是让一个属性从开始到结束的变化可视化了。如果你需要循环的可视化,请查看CSS animation
属性。)
transition-property
指定一个或多个CSS属性的名字,这些属性将会被应用过渡效果。只有被列在此处的属性会在过渡中产生动画效果;其他属性的变化还是像往常一样立刻发生。
transition-duration
给过渡指定时长。你可以指定一个时长给所有会产生过渡效果的属性,也可以指定多个值,让每个属性都拥有不同的过渡时长。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<style>
.parent {
width: 200px;
height: 200px;
border: 1px solid black;
position: relative;
}
.box {
width: 20px;
height: 20px;
left: 0;
top: 0;
background: lightblue;
position: absolute;
transition-property: width height left top background;
transition-duration: 1s;
}
.box1 {
width: 50px;
height: 50px;
left: 100px;
top: 100px;
background: lightgreen;
position: absolute;
transition-property: width height left top background;
transition-duration: 1s;
}
</style>
</head>
<body>
<div class="parent">
<div class="box"></div>
</div>
<script>
function updateTransition() {
let el = document.querySelector('div.box');
if (el) {
el.className = 'box1';
} else {
el = document.querySelector('div.box1');
el.className = 'box';
}
}
setInterval(updateTransition, 1000);
</script>
</body>
</html>
transition-timing-function
指定一个函数来定义属性的中间值是如何计算的。Timing function 决定了过渡的中间值是如何计算的。大多数的 timing function 都可以通过相应函数的图像来指定,如四点定义的贝塞尔曲线图像。你也可以从缓动函数备忘单中选择缓动效果(easing)。
transition-delay
定义在属性改变和过渡真正开始之前等待多久。
缩写语法
transition: <property> <duration> <timing-function> <delay>;
例子
简单例子
这个例子执行一个4秒的字体大小过渡和一个2秒的用户鼠标放到元素之上和动画效果真正开始之间的延迟。
#delay {
font-size: 14px;
transition-property: font-size;
transition-duration: 4s;
transition-delay: 2s;
}
#delay:hover {
font-size: 36px;
}
多个将会产生动画效果的属性的例子
CSS 内容
.box {
border-style: solid;
border-width: 1px;
display: block;
width: 100px;
height: 100px;
background-color: #0000FF;
-webkit-transition: width 2s, height 2s, background-color 2s, -webkit-transform 2s;
transition: width 2s, height 2s, background-color 2s, transform 2s;
}
.box:hover {
background-color: #FFCCCC;
width: 200px;
height: 200px;
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
这个盒子结合了width
, height
, background-color
, transform
四种属性的过渡。
当属性值列表长度不一时
当任何属性的值列表比其他属性更短时,它的值将会不断重复来让使得它们匹配。例如:
div {
transition-property: opacity, left, top, height;
transition-duration: 3s, 5s;
}
等同于:
div {
transition-property: opacity, left, top, height;
transition-duration: 3s, 5s, 3s, 5s;
}
同样的,如果任何属性值列表比transition-property
的值列表更长,那么它将被截取,所以如果你有如下CSS:
div {
transition-property: opacity, left;
transition-duration: 3s, 5s, 2s, 1s;
}
这会被解释为以下内容:
div {
transition-property: opacity, left;
transition-duration: 3s, 5s;
}
在高亮菜单时使用transition
有一个常见的CSS用例:当用户的鼠标悬停在菜单里的某一项时,这一项会高亮。我们可以使用transition
来让这个效果变得更有吸引力。
在我们看代码片段之前,你可能想看看 live demo(假定你的浏览器支持transition
)。
首先,我们设置菜单所要用到的HTML:
<nav>
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact Us</a>
<a href="#">Links</a>
</nav>
然后我们创建CSS来实现我们菜单的外表和感觉。相关的片段如下:
a {
color: #fff;
background-color: #333;
transition: all 1s ease-out;
}
a:hover,
a:focus {
color: #333;
background-color: #fff;
}
这个CSS创建了菜单的外表,并且背景和文字颜色都会在它的元素处于:hover
和:focus
状态时变化。
JavaScript 的例子
在如下情况之后立即使用transition
应当特别小心:
- 用
.appendChild()
将元素添加到DOM中。 - 删除元素的
display: none;
属性。
这些情况下,初始状态会好像从未发生,并且元素总是处于它最后的状态。克服这些限制的最简单方式就是在你打算改变应用过渡效果的属性的时候,使用window.setTimeout()
设置一个合适的时间来延迟执行。
利用transition
让 JavaScript 效果更平滑
transition
是一个可以使得事物变得更加平滑的好工具,这并不需要对你的 JavaScript 做任何事情。看看下面的例子。
<p>Click anywhere to move the ball</p>
<div id="foo"></div>
利用 JavaScript 你可以做出让小球移动到点击位置的中间的效果:
var f = document.getElementById('foo');
document.addEventListener('click', function(ev){
f.style.transform = 'translateY('+(ev.clientY-25)+'px)';
f.style.transform += 'translateX('+(ev.clientX-25)+'px)';
},false);
利用CSS你可以让这一过程更加平滑而且不需要任何额外的 JavaScript 工作。仅仅对元素添加一个transition
,一切将会变得丝滑。
p {
padding-left: 60px;
}
#foo {
border-radius: 50px;
width: 50px;
height: 50px;
background: #c00;
position: absolute;
top: 0;
left: 0;
transition: transform 1s;
}
你可以在这里找到demo。
检测transition
的开始和结束
你可以使用transitioned
事件来检测一段动画是否结束。这是一个TransitionEvent
对象,它在典型的Event
对象基础上新添了两个额外的属性:
propertyName
一个字符串,指示了结束了过渡效果的CSS属性的名称。
elapsedTime
一个浮点数,指示了过渡从事件开始时已经运行了的秒数。这个值不被transition-delay
所影响。
通常,你可以使用addEventListener()
方法来监听这个事件:
el.addEventListener("transitionend", updateTransition, true);
你还可以用transitionrun
(在任何延迟之前触发)和transitionstart
(在任何延迟之后触发)来检测transition
的开始:
el.addEventListener("transitionrun", signalStart, true);
el.addEventListener("transitionstart", signalStart, true);
注意:如果
transition
在transition
完成之前被取消,那么transitionend
事件不会被触发。这是因为在这种情况下要么这个元素被设置为了display: none
,要么动画属性的值被改变了。
更新于Mar 23, 2019, 8:15:15 PM。部分live demo不能链接过来,请前往原文进行查看。