經過過渡transition,可讓web前端開發人員不須要javascript就能夠實現簡單的動畫交互效果。過渡屬性看似簡單,但實際上它有不少須要注意的細節和容易混淆的地方。本文將介紹和梳理關於CSS過渡的知識javascript
過渡transition是一個複合屬性,包括transition-property、transition-duration、transition-timing-function、transition-delay這四個子屬性。經過這四個子屬性的配合來完成一個完整的過渡效果css
transition-property: 過渡屬性(默認值爲all) transition-duration: 過渡持續時間(默認值爲0s) transiton-timing-function: 過渡函數(默認值爲ease函數) transition-delay: 過渡延遲時間(默認值爲0s)
[注意]IE9-不支持該屬性,safari3.1-六、IOS3.2-6.一、android2.1-4.3須要添加-webkit-前綴;而其他高版本瀏覽器支持標準寫法html
.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; }
<div class="test"></div>
//鼠標移動到元素上,會出現寬度變化效果前端
複合屬性java
過渡transition的這四個子屬性只有<transition-duration>是必需值且不能爲0。其中,<transition-duration>和<transition-delay>都是時間。當兩個時間同時出現時,第一個是<transition-duration>,第二個是<transition-delay>;當只有一個時間時,它是<transition-duration>,而<transition-delay>爲默認值0android
transition: <transition-property> || <transition-duration> || <transition-timing-function> || <transition-delay>
[注意]transition的這四個子屬性之間不能用逗號隔開,只能用空格隔開。由於逗號隔開的表明不一樣的屬性(transition屬性支持多值,多值部分稍後介紹);而空格隔開的表明不一樣屬性的四個關於過渡的子屬性web
.test{ height: 100px; width: 100px; background-color: pink; /*表明持續時間爲2s,延遲時間爲默認值0s*/ transition;2s; } .test:hover{ width: 500px; }
<div class="test"></div>
.test{ height: 100px; width: 100px; background-color: pink; /*表明持續時間爲1s,延遲時間爲2s*/ transition: 1s 2s; } .test:hover{ width: 500px; }
<div class="test"></div>
transition-propertychrome
值: none | all | <transition-property>[,<transition-property>]*瀏覽器
初始值: 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
值: <time>[,<time>]*
初始值: 0s
應用於: 全部元素
繼承性: 無
[注意]該屬性不能爲負值
[注意]若該屬性爲0s則爲默認值,若爲0則爲無效值。因此必須帶單位
[注意]該值爲單值時,即全部過渡屬性都對應一樣時間;該值爲多值時,過渡屬性按照順序對應持續時間
//DEMO中的過渡屬性值 transition-property: width,background;
該屬性定義元素屬性延遲多少時間後開始過渡效果,該屬性的單位是秒s或毫秒ms
transition-delay
值: <time>[,<time>]*
初始值: 0s
應用於: 全部元素
繼承性: 無
[注意]該屬性若爲負值,無延遲效果,但過渡元素的起始值將從0變成設定值(設定值=延遲時間+持續時間)。若該設定值小於等於0,則無過渡效果;若該設定值大於0,則過渡元素從該設定值開始完成剩餘的過渡效果
[注意]若該屬性爲0s則爲默認值,若爲0則爲無效值。因此必須帶單位
[注意]該值爲單值時,即全部過渡屬性都對應一樣時間;該值爲多值時,過渡屬性按照順序對應持續時間
//DEMO中的過渡屬性值 transition-property: width,background;
過渡時間函數用於定義元素過渡屬性隨時間變化的過渡速度變化效果
transition-timing-function
值: <timing-function>[,<timing-function>]*
初始值: ease
應用於: 全部元素
繼承性: 無
取值
過渡時間函數共三種取值,分別是關鍵字、steps函數和bezier函數
steps函數
steps步進函數將過渡時間劃分紅大小相等的時間時隔來運行
steps步進函數爲
steps(<integer>[,start | end]?)
<integer>:用來指定間隔個數(該值只能是正整數)
第二個參數: 該參數可選,默認是end,表示開始值保持一次;若參數爲start,表示開始不保持
貝塞爾曲線
貝塞爾曲線經過p0-p3四個控制點來控制,其中p0表示(0,0),p3表示(1,1)。而<transition-timing-function>就是經過肯定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: <single-transition>[,<single-transition>]*
<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; }
<div class="box"> <div class="test">test</div> </div>
【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-六、ISO3.2-6.一、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> <div id="test"></div> <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> <div id="test"></div> <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、android test.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、android test.addEventListener("webkitTransitionEnd", myFunction); // 標準語法 test.addEventListener("transitionend", myFunction); function myFunction() { index++; this.innerHTML = index; if(index == 1){ test.removeEventListener("webkitTransitionEnd", myFunction); test.removeEventListener("transitionend", myFunction); } }