透過過渡transition,可以讓web前端開發人員不需要javascript就可以實現簡單的動畫互動效果。過渡屬性看似簡單,但實際上它有許多需要注意的細節和容易混淆的地方。本文將介紹和整理關於CSS過渡的知識
# 過渡transition是一個複合屬性,包括transition-property、transition-duration、transition-timing-function 、transition-delay這四個子屬性。透過這四個子屬性的配合來完成一個完整的過渡效果
transition-property: 过渡属性(默认值为all) transition-duration: 过渡持续时间(默认值为0s) transiton-timing-function: 过渡函数(默认值为ease函数) transition-delay: 过渡延迟时间(默认值为0s)
[注意]IE9-不支援該屬性,safari3 .1-6、IOS3.2-6.1、android2.1-4.3需要添加-webkit-前綴;而其餘高版本瀏覽器支援標準寫法
.test{ height: 100px; width: 100px; background-color: pink; transition-duration: 3s;/* 以下三值为默认值,稍后会详细介绍 */ transition-property: all; transition-timing-function: ease; transition-delay: 0s; } .test:hover{ width: 500px; }
4533d610cdb8960dc10af1294aeeedba94b3e26ee717c64999d7867364b1b4a3
//滑鼠移到元素上,會出現寬度變化效果
複合屬性
過渡transition的這四個子屬性只有31f21fdecc9239726c6c3ef1640f525f是必要值且不能為0。其中,31f21fdecc9239726c6c3ef1640f525f和4fdf89e653de7fdc9ea3c2c68311be4b都是時間。當兩個時間同時出現時,第一個是31f21fdecc9239726c6c3ef1640f525f,第二個是4fdf89e653de7fdc9ea3c2c68311be4b;當只有一個時間時,它是31f21fdecc9239726c6c3ef1640f525f,而76ef2ded2afa3523c0fbf27bf77b92f1為預設值0
transition: <transition-property> || <transition-duration> || <transition-timing-function> || <transition-delay>
# [注意]transition的這四個子屬性之間不能用逗號隔開,只能用空格隔開。因為逗號隔開的代表不同的屬性(transition屬性支援多值,多值部分稍後介紹);而空格隔開的代表不同屬性的四個關於過渡的子屬性
.test{ height: 100px; width: 100px; background-color: pink;/*代表持续时间为2s,延迟时间为默认值0s*/ transition;2s;} .test:hover{ width: 500px; }
<p class="test"></p>
.test{ height: 100px; width: 100px; background-color: pink; /*代表持续时间为1s,延迟时间为2s*/ transition: 1s 2s; } .test:hover{ width: 500px; }
<p class="test"></p>
#
值: none | all | b0cfce2f2b39e6de691805c0c093e47f[,b0cfce2f2b39e6de691805c0c093e47f]*
初始值: all
應用於: 所有元素
繼承性: 無
none: 没有指定任何样式 all: 默认值,表示指定元素所有支持transition-property属性的样式<transition-property>: 可过渡的样式,可用逗号分开写多个样式可過渡的樣式
不是所有的CSS樣式值都可以過渡,只有具有中間值的屬性才具備過渡效果
Vstart = 开始值; Vend = 结束值; Vres = 中间值; p = 过渡函数的输出值 Vres = (1 - p) * Vstart + p * Vend 当Vres具有有效值时,则该CSS样式可过渡
颜色: color background-color border-color outline-color 位置: backround-position left right top bottom 长度: [1]max-height min-height max-width min-width height width [2]border-width margin padding outline-width outline-offset [3]font-size line-height text-indent vertical-align [4]border-spacing letter-spacing word-spacing 数字: opacity visibility z-index font-weight zoom 组合: text-shadow transform box-shadow clip 其他: gradient
#過渡持續時間
該屬性的單位是秒s或毫秒ms
transition-duration
值: 46dd80ba616c57a652514755c74c4211[,46dd80ba616c57a652514755c74c4211]*
初始值: 0s
套用於: 所有元素
繼承性: 無
[注意]該屬性不能為負值
[注意]若該屬性為0s則為預設值,若為0則為無效值。所以必須帶單位
[注意]該值為單值時,即所有過渡屬性都對應同樣時間;該值為多值時,過渡屬性按照順序對應持續時間
#
//DEMO中的过渡属性值transition-property: width,background;
過渡延遲時間
此屬性定義元素屬性延遲多少時間後來開始過渡效果,此屬性的單位是秒s或毫秒ms
//DEMO中的过渡属性值transition-property: width,background;##################### ######過渡時間函數###### 過渡時間函數用於定義元素過渡屬性隨時間變化的過渡速度變化效果######transition-timing-function###### 值: 66aa3d34d47552b7b986fe2a4b5468d0[,66aa3d34d47552b7b986fe2a4b5468d0]*######初始值: ease###### 應用於: 所有元素###### 繼承性: 無######取值###### 過渡時間函數共三種取值,分別是關鍵字、steps函數和bezier函數######steps函數###### steps步進函數將過渡時間分成大小相等的時間時隔來運行###### steps步進函數為############
steps(<integer>[,start | end]?)###################
<integer>:用来指定间隔个数(该值只能是正整数) 第二个参数: 该参数可选,默认是end,表示开始值保持一次;若参数为start,表示开始不保持#################################
transition-timing-function: cubic-bezier(x1,y1,x2,y2);################## ############貝塞爾曲線###### 貝塞爾曲線透過p0-p3四個控制點來控制,其中p0表示(0,0),p3表示(1 ,1)。而0cd58b9f0f99543f030aa199cd93c8c9就是透過確定p1(x1,y1)和p2(x2,y2)的值來決定的###
transition-timing-function: cubic-bezier(x1,y1,x2,y2);
[注意]x1,y1,x2,y2都是0到1的值(包括0和1)
关键字
关键字其实是bezier函数或steps函数的特殊值
ease: 开始和结束慢,中间快。相当于cubic-bezier(0.25,0.1,0.25,1) linear: 匀速。相当于cubic-bezier(0,0,1,1) ease-in: 开始慢。相当于cubic-bezier(0.42,0,1,1) ease-out: 结束慢。相当于cubic-bezier(0,0,0.58,1) ease-in-out: 和ease类似,但比ease幅度大。相当于cubic-bezier(0.42,0,0.58,1) step-start: 直接位于结束处。相当于steps(1,start) step-end: 位于开始处经过时间间隔后结束。相当于steps(1,end)
transition的多个属性值用逗号分隔开表示可以同时为多个值设置过渡属性
transtion: 09f907df7377e66249f520fd04c5fd69[,09f907df7377e66249f520fd04c5fd69]*
<single-transition>: <transition-property> || <transition-duration> || <transition-timing-function> || <transition-delay>
//property为all,timing-function为linear,delay为0s,duration为0s。表示无过渡行为transition: 0s;
【1】若不同的transition-property值,对应的transition-delay | transition-timing-function | transition-duration的属性值都相同时,则对应的这些属性设置一个即可
#test1{ transition-property: width,background; transition-delay: 200ms; transition-timing-function: linear; transition-duration: 2s; }/*类似于*/#test2{ transition: width 2s linear 200ms,background 2s linear 200ms; }
【2】当transition-property值的个数多于对应的transition-delay | transition-timing-function | transition-duration的属性值(属性值的个数大于1个)时,将按顺序开始取值
#test1{ transition-property: width,background,opacity; transition-duration: 2s,500ms; transition-timing-function: linear,ease; transition-delay: 200ms,0s; }/*类似于*/#test2{ transition: width 2s linear 200ms,background 500ms ease 0s,opacity 2s linear 200ms; }
【3】当transition-property值的个数少于对应的transition-delay | transition-timing-function | transition-duration的属性值个数时,多余的属性值将无效
#test1{ transition-property: width; transition-duration: 2s,500ms; transition-timing-function: linear,ease; transition-delay: 200ms,0s; }/*类似于*/#test2{ transition: width 2s linear 200ms; }
【4】当transition-property的值中出现一个无效值,它依然按顺序对应transition的其他属性值(其他属性出现无效值,处理情况也类似)
#test1{ transition-property: width,wuxiao,background; transition-duration: 2s,500ms; transition-timing-function: linear,ease; transition-delay: 200ms,0s; }/*类似于*/#test2{ transition: width 2s linear 200ms,background 2s linear 200ms; }
【5】当transition-property的值中,有些值重复出现多次,则以最后出现的值为准,前面所有出现的值都被认定为无效值,但依然按顺序对应transition的其他属性值
#test1{ transition-property: width,width,background; transition-duration: 2s,500ms; transition-timing-function: linear,ease; transition-delay: 200ms,0s; }/*类似于*/#test2{ transition: width 500ms ease 0s,background 2s linear 200ms; }
【1】过渡开始时间=样式改变的时刻+过渡延迟时间;而过渡结束时间=过渡开始时间+过渡持续时间
【2】过渡起始值=过渡前的过渡属性值;而过渡结束值=过渡完成后的过渡属性值
【3】过渡分为两个阶段:前进(forward)和反向(reverse)。若前进阶段进行一段时间后进入反向阶段,则反向阶段的初始值是前进阶段结束时的瞬时值
【4】以hover为例,若在元素非hover态时设置transition,相当于设置的反向状态。而前进和反向是一致的。而如果在元素hover态设置transition,则前进状态以hover态设置的为准,而反向状态以非hover态设置的为准
.test{ width: 100px; transition: 3s; } .test:hover{ width: 500px; transition: 500ms; }
【5】如果子元素和父元素过渡属性都一致。若触发子元素过渡时,父元素正在过渡,则将父元素过渡的中间态的值作为子元素过渡的初始值
.box:hover{ font-size: 50px; } .test:hover{ font-size: 30px; }
<p class="box"> <p class="test">test</p> </p>
【6】若过渡起始值或过渡开始值为auto,则浏览器不会自己计算成具体数字值,而是不发生过渡效果。所以要过渡某些属性,首先需要将其重置成具体数字值
[注意]低版本webkit内核浏览器存在bug,会产生反向的过渡效果
.test{ width: 100px; -webkit-transition: width 2s; transition:width 2s; } .test:hover{ width:auto; }
【7】隐式过渡是指一个属性改变时引起另一个属性的改变。如border-width是1em,则font-size改变时,border-width也会相应的改变。firefox和IE浏览器支持隐式过渡。而webkit内核浏览器不支持隐式过渡。
.test{ border: 1px solid black; -webkit-transition: font-size 2s; transition:font-size 2s; font: 20px/100px "宋体"; } .test:hover{ font-size: 40px; border-right-width: 1em; }
一般地,过渡transition的触发有三种方式,分别是伪类触发、媒体查询触发和javascript触发。其中常用伪类触发包括:hover、:focus、:active等
【1】hover
鼠标悬停触发
【2】active
用户单击元素并按住鼠标时触发
【3】focus
获得焦点时触发
【4】@media触发
符合媒体查询条件时触发
/* 把浏览器的宽度拖动到小于1000px时触发 */@media (max-width: 1000px){ .test{ width: 500px; } }
【5】点击事件
用户点击元素时触发
test.onclick = function(){ test.style.width = '300px'; setTimeout(function(){ test.style.width = '100px'; },3000); }
关于过渡transition的事件只有一个,是transitionend事件,它发生在过渡事件完成后
[注意]safari3.1-6、ISO3.2-6.1、android2.1-4.3需要使用webkitTransitionEnd事件
属性
transitionEnd的事件对象具有以下3个私有属性
propertyName:发生transition效果的CSS属性名
elapsedTime:代表发生实际效果的持续时间。若完整进行,则返回完整时间;若中途中断,则返回实际时间
[注意]该属性具有兼容性问题,chrome返回持续时间加延迟时间,而其他浏览器只返回持续时间
<style>#test{height: 100px;width: 100px;background-color: pink; transition: width 1.5s 0.5s;}#test:hover{width: 200px;}</style><p id="test"></p><script>test.addEventListener("transitionend", myFunction);function myFunction(e){ e = e || event; test.innerHTML = 'propertyName:' + e.propertyName + '; elapsedTime:' + e.elapsedTime + '; pseudoElement:' + e.pseudoElement; }</script>
pseudoElement:如果transition效果发生在伪元素,会返回该伪元素的名称,以“::”开头。如果不发生在伪元素上,则返回一个空字符串''
[注意]若transition效果发生在伪元素上,IE浏览器将不会触发transitionEnd事件
<style>#test{height: 100px;width: 100px;position: relative;background-color: lightblue;}#test:before{content:'我是伪元素';position: absolute;height: 100px;width: 100px;background-color: pink; left:200px;}#test:hover:before{width: 200px;transition: width 1.5s 0.5s;}</style><p id="test"></p><script>test.addEventListener("transitionend", myFunction);function myFunction(e){ console.log(event) e = e || event; test.innerHTML = 'propertyName:' + e.propertyName + '; elapsedTime:' + e.elapsedTime + '; pseudoElement:' + e.pseudoElement; }</script>
注意事项
【1】过渡分为两个阶段:前进阶段和反向阶段。transitionend事件在前进阶段结束时会触发,在反向阶段结束时也会触发
var index = 0;//兼容低版本safari、IOS、androidtest.addEventListener("webkitTransitionEnd", myFunction);// 标准语法test.addEventListener("transitionend", myFunction);function myFunction() { index++; this.innerHTML = index;}
【2】过渡事件触发的次数与transition-property过渡属性的个数有关。过渡属性有几个就会触发几次
transition: width 1s,background-color 1s; -webkit-transition: width 1s,background-color 1s;
【3】如果过渡属性是复合属性,如border-width相当于是border-top-width、border-bottom-width、border-left-width和border-right-width这四个属性的集合。则过渡事件触发4次
[注意]在低版本webkit内核浏览器里只触发1次
transition:border-width 1s; -webkit-transition: border-width 1s;
【4】如果过渡属性是默认值all,则过渡事件的次数是计算后的非复合的过渡属性的个数。如果发生过渡的属性是border-width和width,则经过计算后过渡事件应该触发5次
[注意]在低版本webkit内核浏览器中处理情况也一致
.test{ width: 50px; border: 1px solid black; transition:all 1s; -webkit-transition: all 1s; } .test:hover{ border-width: 10px; width: 100px; }
【5】如果过渡延迟时间为负值,且绝对值大于等于过渡持续时间时,低版本webkit内核浏览器不会产生过渡效果,但会触发过渡事件;而其他浏览器即不会产生过渡效果,也不会触发过渡事件
transition:width 1s -1s; -webkit-transition: width 1s -1s;
【6】如果过渡属性存在复合属性及该复合属性包含的非复合属性,则浏览器计算复合属性的子属性时,不会重复计算已包含的属性
[注意]低版本webkit内核浏览器会出现bug,不仅复合属性被当作一个属性来触发事件,而且会多触发一次
.test{ border: 1px solid black; transition:border-width 1s,border-left-width 2s; -webkit-transition: border-width 1s,border-left-width 2s; } .test:hover{ border-width:10px; }
[注意]当过渡事件执行完后,应及时使用removeEventListener取消绑定,以免对其他效果造成影响
var index = 0;//兼容低版本safari、IOS、androidtest.addEventListener("webkitTransitionEnd", myFunction);// 标准语法test.addEventListener("transitionend", myFunction);function myFunction() { index++; this.innerHTML = index; if(index == 1){ test.removeEventListener("webkitTransitionEnd", myFunction); test.removeEventListener("transitionend", myFunction); } }
更多CSS过渡transition 相关文章请关注PHP中文网!