CSS

CSS Transitions: Using CSS transitions

CSS转换:使用CSS转换

CSS transitions 提供了一种在更改CSS属性时控制动画速度的方法。 其可以让属性变化成为一个持续一段时间的过程,而不是立即生效的。比如,将一个元素的颜色从白色改为黑色,通常这个改变是立即生效的,使用 CSS transitions 后该元素的颜色将逐渐从白色变为黑色,按照一定的曲线速率变化。这个过程可以自定义。

通常将两个状态之间的过渡称为隐式过渡(implicit transitions),因为开始与结束之间的状态由浏览器决定。

CSS transitions 可以决定哪些属性发生动画效果 (明确地列出这些属性),何时开始 (设置 delay),持续多久 (设置 duration) 以及如何动画 (定义timing funtion,比如匀速地或先快后慢)。

注:transition 可以不用厂商前缀,不过鉴于标准刚刚稳定,对于基于 Webkit的浏览器仍然需要厂商前缀。如果想兼容旧版本的浏览器那么也需要厂商前缀(例如Firefox 15 及之前版本, Opera 12 及之前版本)。详情见本页底部的兼容性表格。

哪些 CSS 属性可以动画?

网页制作者可以定义哪个属性以哪种方式动画,这样能制作出复杂的过渡。因为有些属性动画无意义,所以 可动画属性列表 是一个有限集合。

注意:可动画的属性集将有变动,开发者应关注。

auto 值常常较复杂,规范指出不要在它上动画。一些用户代理,比如基于 Gecko 的,遵循这点;一些,比如基于 WebKit的,没有这么严格限制。在 auto 上动画结果可能不可预期,这取决于浏览器及其版本,应当避免使用。

同时应当留意这种情形,在插入元素(如.appendChild())或改变属性display: none后立即使用过渡, 元素将视为没有开始状态,始终处于结束状态。简单的解决办法,改变属性前用window.setTimeout()延迟几毫秒。

多动画属性示例

HTML内容

<body>     <p>The box below combines transitions for: width, height, background-color, transform. Hover over the box to see these properties animated.</p>     <div class="box">Sample</div> </body>

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 }

定义过渡

css转换使用速记控制。transition财产。这是配置转换的最佳方法,因为这样可以更容易地避免参数列表的长度不同步,而这可能会使您不得不花费大量时间调试CSS。

可以使用以下子属性控制转换的各个组件:

(注意下面示例中过渡无限循环是为了说明例子,过渡只是从开始到结束变化,如果需要循环,查看 animation 。)

transition-property指定哪个或哪些 CSS 属性用于过渡。只有指定的属性才会在过渡中发生动画,其它属性仍如通常那样瞬间变化。transition-duration指定过渡的时长。或者为所有属性指定一个值,或者指定多个值,为每个属性指定不同的时长。

transition-duration: 0.5s

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height:125px;} .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position:absolute; -webkit-transition-property: width height background-color font-size left top transform -webkit-transform color; -webkit-transition-duration: 0.5s; -webkit-transition-timing-function: ease-in-out; transition-property: width height background-color font-size left top transform -webkit-transform color; transition-duration: 0.5s; transition-timing-function: ease-in-out; } .box1{ transform: rotate(270deg -webkit-transform: rotate(270deg width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top: 25px; position: absolute; -webkit-transition-property: width height background-color font-size left top transform -webkit-transform color; -webkit-transition-duration: 0.5s; -webkit-transition-timing-function: ease-in-out; transition-property: width height background-color font-size left top transform -webkit-transformv color; transition-duration: 0.5s; transition-timing-function: ease-in-out; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-duration: 1s

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height:125px;} .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top -webkit-transform color; -webkit-transition-duration: 1s; -webkit-transition-timing-function: ease-in-out; transition-property: width height background-color font-size left top transform color; transition-duration: 1s; transition-timing-function: ease-in-out; } .box1{ transform: rotate(270deg -webkit-transform: rotate(270deg width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top: 25px; position: absolute; -webkit-transition-property: width height background-color font-size left top -webkit-transform transform color; -webkit-transition-duration: 1s; -webkit-transition-timing-function: ease-in-out; transition-property: width height background-color font-size left top transform -webkit-transform color; transition-duration: 1s; transition-timing-function: ease-in-out; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-duration: 2s

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height:125px;} .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top transform -webkit-transform color; -webkit-transition-duration: 2s; -webkit-transition-timing-function: ease-in-out; transition-property: width height background-color font-size left top transform -webkit-transform color; transition-duration: 2s; transition-timing-function: ease-in-out; } .box1{ transform: rotate(270deg -webkit-transform: rotate(270deg width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top: 25px; position: absolute; -webkit-transition-property: width height background-color font-size left top transform -webkit-transform color; -webkit-transition-duration: 2s; -webkit-transition-timing-function: ease-in-out; transition-property: width height background-color font-size left top transform -webkit-transform color; transition-duration: 2s; transition-timing-function: ease-in-out; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-duration: 4s

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height:125px;} .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top transform -webkit-transform color; -webkit-transition-duration: 4s; -webkit-transition-timing-function: ease-in-out; transition-property: width height background-color font-size left top transform -webkit-transform color; transition-duration: 4s; transition-timing-function: ease-in-out; } .box1{ transform: rotate(270deg -webkit-transform: rotate(270deg width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top: 25px; position: absolute; -webkit-transition-property: width height background-color font-size left top transform -webkit-transform color; -webkit-transition-duration: 4s; -webkit-transition-timing-function: ease-in-out; transition-property: width height background-color font-size left top transform -webkit-transform color; transition-duration: 4s; transition-timing-function: ease-in-out; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-timing-function

指定一个函数,定义属性值怎么变化。缓动函数 Timing functions 定义属性如何计算。多数 timing functions 由四点定义一个 bezier 曲线。也可以从 Easing Functions Cheat Sheet 选择缓动效果。

transition-timing-function: ease

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height:125px;} .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-timing-function: ease; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-timing-function: ease; } .box1{ width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top: 25px; position:absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-timing-function: ease; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-timing-function: ease; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-timing-function: linear

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height:125px;} .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-timing-function: linear; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-timing-function: linear; } .box1{ width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top:25px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-timing-function: linear; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-timing-function: linear; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-timing-function: step-end

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height:125px;} .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-timing-function: step-end; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-timing-function: step-end; } .box1{ width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top:25px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-timing-function: step-end; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-timing-function: step-end; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-timing-function: steps(4, end)

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height:125px;} .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-timing-function: steps(4, end transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-timing-function: steps(4, end } .box1{ width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top: 25px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-timing-function: steps(4, end transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-timing-function: steps(4, end }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-delay指定延迟,即属性开始变化时与过渡开始发生时之间的时长。

transition-delay: 0.5s

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height: 125px; } .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-delay: 0.5s; -webkit-transition-timing-function: linear; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-delay: 0.5s; transition-timing-function: linear; } .box1 { width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top:25px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-delay: 0.5s; -webkit-transition-timing-function: linear; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-delay: 0.5s; transition-timing-function: linear; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-delay: 1s

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height: 125px; } .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-delay: 1s; -webkit-transition-timing-function: linear; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-delay: 1s; transition-timing-function: linear; } .box1{ width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top: 25px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-delay: 1s; -webkit-transition-timing-function: linear; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-delay: 1s; transition-timing-function: linear; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-delay: 2s

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height: 125px; } .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-delay: 2s; -webkit-transition-timing-function: linear; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-delay: 2s; transition-timing-function: linear; } .box1 { width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top: 25px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-delay: 2s; -webkit-transition-timing-function: linear; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-delay: 2s; transition-timing-function: linear; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

transition-delay: 4s

<div class="parent"> <div class="box">Lorem</div> </div>

.parent { width: 250px; height: 125px; } .box { width: 100px; height: 100px; background-color: red; font-size: 20px; left: 0px; top: 0px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-delay: 4s; -webkit-transition-timing-function: ease-in-out; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-delay: 4s; transition-timing-function: ease-in-out; } .box1 { width: 50px; height: 50px; background-color: blue; color: yellow; font-size: 18px; left: 150px; top: 25px; position: absolute; -webkit-transition-property: width height background-color font-size left top color; -webkit-transition-duration: 2s; -webkit-transition-delay: 4s; -webkit-transition-timing-function: ease-in-out; transition-property: width height background-color font-size left top color; transition-duration: 2s; transition-delay: 4s; transition-timing-function: ease-in-out; }

function updateTransition() { var el = document.querySelector("div.box" if (el) { el.className = "box1"; } else { el = document.querySelector("div.box1" el.className = "box"; } return el; } var intervalID = window.setInterval(updateTransition, 7000

简写的CSS语法如下:

div { transition: <property> <duration> <timing-function> <delay>; }

检测过渡是否完成

当过渡完成时触发一个事件,在符合标准的浏览器下,这个事件是 transitionend, 在 WebKit 下是 webkitTransitionEnd. 详情查看页面底部的兼容性表格。 transitionend 事件提供两个属性:

propertyName字符串,指示已完成过渡的属性。elapsedTime浮点数,指示当触发这个事件时过渡已运行的时间(秒)。这个值不受transition-delay影响。

与往常一样,您可以使用addEventListener()方法来监视此事件:

el.addEventListener("transitionend", updateTransition, true

使用transitionrun(在任何延迟之前触发)和transitionstart(在任何延迟之后触发),以相同的方式检测转换的开始:

el.addEventListener("transitionrun", signalStart, true el.addEventListener("transitionstart", signalStart, true

:如果取消了过渡则不会触发 transitionend事件,因为在过渡完成前动画的属性值改变了。

当属性值列表长度不一致时

transition-property的值列表长度为标准,如果某个属性值列表长度短于它的,则重复其值以长度一致, 例如:

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的,将被截短。 例如:

div {   transition-property: opacity, left;   transition-duration: 3s, 5s, 2s, 1s; }

将按下面这样处理:

div {   transition-property: opacity, left;   transition-duration: 3s, 5s; }

简单例子

这个例子实现这样的效果:4s 过渡改变字体大小,2s 延迟——在元素上鼠标悬停时与开始动画效果之间:

#delay { font-size: 14px; transition-property: font-size; transition-duration: 4s; transition-delay: 2s; } #delay:hover { font-size: 36px; }

高亮菜单过渡效果

CSS 的一个常用地方是当鼠标悬停在菜单上时高亮此菜单,使用 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部分。

transition 让 JavaScript 效果更平滑

transition 是非常好的工具,可以让 JavaScript 效果平滑而不用修改 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 来平滑移动,只用简单地添加一个过渡 :

p { padding-left: 60px; } #foo { border-radius: 50px; width: 50px; height: 50px; background: #c00; position: absolute; top: 0; left: 0; transition: transform 1s; }

你可以在这里演示:http : //jsfiddle.net/9h261pzo/291/

规范

SpecificationStatusComment
CSS TransitionsWorking DraftInitial definition

浏览器兼容性

FeatureChromeFirefox (Gecko)Internet ExplorerOperaSafari (WebKit)
Basic support1.0 -webkit 26.04.0 (2.0) -moz 16.0 (16.0)1010.5 -o 12.103.2 -webkit
transitionend event1.01 26.04.0 (2.0)1010.52 12 12.103.21 6.0

FeatureAndroidFirefox Mobile (Gecko)IE PhoneOpera MobileSafari Mobile
Basic support2.14.0 (2.0) -moz 16.0 (16.0)1010 -o 12.103.2
transitionend event2.114.0 (2.0)10102 12 12.103.21

1. Chrome 1.0,WebKit 3.2和Android 2.1实现了这个非标准webkitTransitionEnd。Chrome 26.0和WebKit 6.0实现该标准transitionend

2. Opera 10.5和Opera Mobile 10实现了这个oTransitionEnd,版本12实现为 otransitionend,版本12.10则为标准transitionend