在網(wǎng)頁設(shè)計中給適當?shù)脑靥砑觿赢嫿换o疑是一個大幅度提升用戶體驗的措施??v觀整個Web開發(fā)的發(fā)展歷史,從最早的原始階段(都是靜態(tài)頁面),到如今這樣一個非常講究用戶體驗的時代,人們越來越在意頁面的表現(xiàn)能力(用戶體驗),干巴巴的展現(xiàn)內(nèi)容往往是沒有什么競爭力的。
就前端開發(fā)這個層面來說,實現(xiàn)動畫的途徑有好幾種。簡單來說可能包括下面幾種方式,
在過去的幾年內(nèi),人們大都在使用第一種或者第二種方法來實現(xiàn)頁面動畫?,F(xiàn)在看來前兩種方法的確很low(第一種方法過重,第二種方法過于繁瑣)。
CSS3的transform
(變換),transition
(過渡),animation
(動畫)三個屬性為純CSS實現(xiàn)動畫提供了有力的支持。本篇文章我們將會詳細的闡述各個屬性的一般性用法,其中將會穿插部分示例。
CSS3新增了屬性transform
,意為變換。那么,什么叫做變換?簡單的來說就是改變元素的大小、位置、形狀等屬性的操作。
??注意:其實transform
還可以分為2D變換和3D變換。前者表示在二維空間進行變換操作(即只有X軸和Y軸),而后者表示在三維空間進行變換操作(即除了二維的X軸和Y軸之外還有一個Z軸)。本篇文章僅對2D變換做闡述,3D變換的相關(guān)內(nèi)容后面會專門作文。
W3C中規(guī)定transform
包含如下幾種操作類型(這里所有的變換都是在2D變換的范疇內(nèi)),
translate
位移rotate
旋轉(zhuǎn)scale
縮放skew
傾斜matrix
變換矩陣一般來說,transform
的語法如下,
transform: none | <transform-function> [ <transform-function>]*
none
為默認值,意為不作任何變換<transform-function>
即為上述提到的各種變換操作<transform-function>
,
,切記。transform-origin
屬性在介紹各種變換操作之前,我覺得很有必要先介紹一下transform-origin
屬性。此屬性不屬于transform
的操作類型,它和transform
屬于同一個level的css屬性,它的作用是用于設(shè)置變換操作的原點。
其語法如下,
transform-origin: [<percentage> | <length> | left | center | right] [<percentage> | <length> | top | center | bottom]?
center center
(50% 50%
),默認變換原點為元素的中心點。<percentage> | <length>
時,可以為負值。記住,所有的二維變換操作都必須基于一個原點,默認的原點為元素的中心點。
此參數(shù)的瀏覽器兼容性如下,
部分支持的瀏覽器需要我們在實際使用時添加各個瀏覽器的私有前綴。
下面我們來看一個例子見識一下改變transform-origin
后的變換效果,
.demo {
transform-origin: 100% 0;
transform: rotate(45deg);
}
效果如下,
圖中左側(cè)的效果應(yīng)用了transform-origin: 100% 0;
導(dǎo)致其旋轉(zhuǎn)變換原點轉(zhuǎn)移到了右上角??捎谟覀?cè)未設(shè)置變換原點的效果圖進行對比體會其變化。
translate
translate
意為位移。它的一般性用法如下,
.demo {
transform: translate(50px, 50px);
}
上面的代碼表示將.demo
元素以其變換原點(元素中心點)為基準,各向右(X軸)和向下(Y軸)移動50px。其效果如下圖,
注意:從上圖的效果中,我們可以看出translate
其實是通過將元素的中心點移動到新的位置來使得整個元素達到位移目的的。
translate(50px, 50px)
是位移操作最基本的用法,其還有如下幾種變形,
translate(50px)
,省略第二個參數(shù),此時只進行X軸位移,Y軸位移量默認為0。translate(0, 50px)
,可以顯式的聲明X軸位移量為0,這樣僅進行Y軸位移。translateX(50px)
,等同于translate(50px, 0)
,只進行X軸位移。translateY(50px)
,等同于translate(0, 50px)
,只進行Y軸位移。rotate
rotate
意為旋轉(zhuǎn)。它的一般性用法如下,
.demo {
transform: rotate(45deg);
}
上面代碼表示將.demo
元素以其變換原點(元素中心點)為基準,順時針旋轉(zhuǎn)45度。效果如下,
rotate(45deg)
,接收一個參數(shù),此參數(shù)表示旋轉(zhuǎn)的度數(shù)。rotate
的參數(shù)可以傳入一個正值,亦可以傳入一個負值(比如-45deg
)。正值表示旋轉(zhuǎn)方向為順時針,負值表示旋轉(zhuǎn)方向為逆時針。scale
scale
意為縮放。它的一般性用法如下,
.demo {
transform: scale(1.5);
}
上面的代碼表示將.demo
元素以其變換原點(元素中心點)為基準,沿著X軸和Y軸放大1.5倍。效果如下,
scale
操作與translate
很相似,scale(1.5)
是其最基本的用法,除此之外它還有如下幾種變形,
scale(1.5, 1.5)
,可以接收兩個參數(shù),分別表示X軸方向與Y軸方向的縮放。其中第二個參數(shù)可以省略。若省略第二個參數(shù),則第二個參數(shù)與第一個參數(shù)一致。scaleX()
或者scaleY()
進行僅對X軸方向或者Y軸方向進行縮放。skew
skew
意為傾斜。它的一般性用法如下,
.demo {
transform: skew(30deg, 30deg);
}
上面的代碼表示將.demo
元素以其變換原點(元素中心點)為基準,沿著X軸順時針傾斜30度,沿著Y軸順時針傾斜30度。效果如下,
注意:skew
在二維變換中是唯一一個可以使元素發(fā)生形變的操作。
skew
與之前的translate
和scale
也是類似的,接收2個參數(shù)。其中第二個參數(shù)可以省略,若省略第二個參數(shù),則第二個參數(shù)將自動使用默認值0deg
。skewX()
和skewY()
進行僅X軸方向或者Y軸方向的傾斜。matrix
關(guān)于matrix
的詳細用法,我這里不想多作闡述。因為這種用法基本很少用到,而且還涉及到一些行列式變換的運算。就是說了我估計我也說不清楚。這里只要知道matrix
是合并了所有的變化操作就行,如果實在有興趣,可自行查閱相關(guān)文檔。
其實,transform
允許對同一元素同時進行多個變換操作,這樣完全可以替代matrix
的用法,而且可讀性更佳。
transform
總結(jié)看到這里,可能會一些看官有個疑問,貌似transform
并不能實現(xiàn)動畫???
沒錯!
僅僅使用transform
是無法實現(xiàn)動畫效果的。因為transform
只是對元素進行生硬的變化,這個變化是瞬間的,所以并沒有展現(xiàn)一種持續(xù)變化的效果。
一般地,我們可以將其與下面即將說道的transition
搭配使用來得到各種動畫效果。
不過,在適當?shù)臅r候使用transform
可以大大簡化頁面實現(xiàn)復(fù)雜度,比如有一個比較復(fù)雜的展示元素,我們現(xiàn)在需要一個與之水平對稱的展示,那么此時只需要rotate
即可。
上面所有效果可以在這個demo中進行試驗。
W3C中css3-transition的文檔對transition
的定義是這樣的,
CSS Transitions allows property changes in CSS values to occur smoothly over a specified duration.
意思就是:允許css的屬性值在一定的時間區(qū)間內(nèi)平滑地過渡。這種效果可以在鼠標單擊、獲得焦點、被點擊或?qū)υ厝魏胃淖冎杏|發(fā),并圓滑地以動畫效果改變CSS的屬性值。
簡單來說,transition
的含義就是元素某一css屬性的過渡。
下面讓我們來詳細看看transition
這貨到底是怎么用的。
transition
的語法如下,
transition:[ transition-property ] || [ transition-duration ] || [ transition-timing-function ] || [ transition-delay ]
可以看出transition
是一個復(fù)合屬性,它包括下面四個子屬性,
transition-property
,用于設(shè)置需要過渡的css屬性transition-duration
,用于設(shè)置過渡的持續(xù)時間transition-timing-function
,用于設(shè)置過渡的速率類型(即過渡的動畫類型)transition-delay
,用于設(shè)置過渡的開始延時此外transition
允許使用,
同時對一個元素進行多個屬性的過渡,比如
.demo {
transition: width 1s ease-out, height 1s ease-in;
}
這樣我們可以對同一個元素的不同的屬性應(yīng)用不同的過渡策略。
下面我們來分別對每個屬性進行描述,其中可能會穿插一些示例。
transition-property
用于設(shè)置需要過渡的css屬性,語法如下,
transition-property:all | none | <property>[ ,<property> ]*
none
,不指定過渡的css屬性all
,此為默認值,指定所有可進行過渡的css屬性<property>
,可自定義需要過渡的css屬性這里值得一提的是,不是所有的css屬性都是可以進行過渡的。比如display
屬性,比如background-image: url(...)
(當設(shè)置背景圖片為一個gradient時反而是可以應(yīng)用過渡的),還有一些沒有明確大小的單位,比如height: auto
,等等。
這篇文章中有一份可過渡的css屬性列表。列表不但指明了哪些css屬性是可以過渡的,還指明了這些css屬性的取值類型(意思就是,這些css屬性必須滿足這些取值條件才可以應(yīng)用過渡效果)。
這里還有一個demo,展示了幾乎所有的transition
效果。
transition-duration
用于設(shè)置過渡的持續(xù)時間,語法如下,
transition-duration:<time>[ ,<time> ]*
這個屬性沒什么可說的,就是用于設(shè)置過渡的持續(xù)時間。過渡時間越短則動畫運行速度越快,過渡時間越長則動畫運行越慢。
此屬性的單位為秒(s
),默認值為0。當設(shè)置為0時,則表示過渡是瞬間完成的。
transition-timing-function
用于設(shè)置過渡的速率類型,語法如下,
transition-timing-function:linear | ease | ease-in | ease-out | ease-in-out | step-start | step-end | steps(<integer>[, [ start | end ] ]?) | cubic-bezier
這個屬性相比之前的兩個屬性要稍微復(fù)雜一點,它的設(shè)置非常多樣化。
linear
(線性過渡),ease
(平滑過渡,此為默認值),ease-in
(由慢到快),ease-out
(由快到慢),ease-in-out
(由慢到快再到慢)cubic-bezier()
,自定義貝塞爾曲線。其實預(yù)設(shè)的幾種都有對應(yīng)的貝塞爾曲線。steps(<integer>[, [ start | end ] ]?)
,接受兩個參數(shù)的步進函數(shù)。第一個參數(shù)必須為正整數(shù),指定函數(shù)的步數(shù)。第二個參數(shù)取值可以是start或end,指定每一步的值發(fā)生變化的時間點。第二個參數(shù)是可選的,默認值為end。step-start
,等同于steps(1, start)
step-end
,等同于steps(1, end)
我想這里唯一需要解釋的就是steps
相關(guān)的幾種過渡速率類型。steps()
的意思就是將整個過渡過程分為特定的步數(shù),并規(guī)定了每一步過渡的執(zhí)行時機。
比如,
transition-property: all;
transition-duration: 2s;
transition-timing-function: steps(5, end);
這段代碼的效果請參見這個demo。
steps(5, end)
的意思就是,
Lea Verou的http://cubic-bezier.com/可以可視化定制各種貝塞爾曲線。
MDN上有對每一種過渡速率類型的效果展示。
transition-delay
用于設(shè)置過渡的開始延時,其語法與transition-duration
是一樣的。這里就不再贅述了。
不過有一點需要注意,當我們使用transition
簡寫模式的時候,一般按照如下的格式來書寫,
.demo {
transition: all 2s ease 1s;
}
除此之外,你可能還會看到別人這么寫,
.demo {
transition: 2s 1s
}
僅指明了兩個時間參數(shù),其他的都使用默認參數(shù)。此時第一個時間參數(shù)為transition-duration
,第二個時間參數(shù)為transition-delay
。
除此之外,我們還可以利用transition-delay
屬性來達到一些酷炫的效果,比如
.demo {
transition: height 1s, width 1s 1s;
}
意思就是先對height
屬性進行過渡,延遲1s后對width
屬性進行過渡,而這個延遲的時間正好是前一個屬性的過渡時間,從而整體看起來非常平滑。詳情可參閱這個demo。
transition
總結(jié)transition
簡單明了,可快速對元素實現(xiàn)一些平滑過渡。不過它也有自己的適用場景和注意事項。
下面是一些使用transition
的注意事項,
transition
時最好添加各個瀏覽器廠商的私有前綴,將W3C的語法放在最后。transition
。transition
需要明確知道開始狀態(tài)和結(jié)束狀態(tài)的具體數(shù)值,才能計算出中間狀態(tài)。transition
的局限,
transition
必須要外力推動,比如鼠標動作,或者js操作等等,否則無法觸發(fā)過渡。transition
的過渡效果是一次性的,除非人為的反復(fù)觸發(fā)。transition
只能接受兩個邊界狀態(tài)(開始和結(jié)束),中間的過渡狀態(tài)是由瀏覽器自動計算的。無法人為的指定中間狀態(tài)。為了解決上述問題,CSS Animation應(yīng)用而生了。
animation
相比transition
制作動畫擁有更高的自定義性,可以定義每一幀的行為。
首先讓我們來看一個模擬月食的demo來體驗一下CSS動畫的魅力。
哈哈,感覺如何,是不是有種很酷炫的感覺。下面讓我們來詳細看看animation
的用法吧。
animation
的語法如下,
animation: [[ animation-name ] || [ animation-duration ] || [ animation-timing-function ] || [ animation-delay ] || [ animation-iteration-count ] || [ animation-direction ]] [ , [ animation-name ] || [ animation-duration ] || [ animation-timing-function ] || [ animation-delay ] || [ animation-iteration-count ] || [ animation-direction ]]*
與transition
一樣,我們可以對同一個元素同時應(yīng)用多個animation
,比如,
@keyframes typing {
from { width: 0; }
}
@keyframes blink-caret {
50% { border-color: transparent; }
}
h1 {
font: bold 200% Consolas, Monaco, monospace;
border-right: .1em solid;
width: 16.5em; /* fallback */
width: 30ch; /* # of chars */
margin: 2em 1em;
white-space: nowrap;
overflow: hidden;
animation: typing 20s steps(30, end), blink-caret .5s step-end infinite alternate;
}
上述代碼可以實現(xiàn)一個非常神奇的效果,它給h1
元素同時應(yīng)用了typing
和blink-caret
兩種動畫,具體的效果可參見這里。
animation
可設(shè)置的屬性還是挺多的,下面讓我們一個個的看看每個屬性的具體用法。
animation-name
animation-name
意為動畫的名稱。如果不設(shè)置animation-name
,那么元素將沒有任何的動畫效果。
其語法如下,
animation-name:none | <identifier> [ , none | <identifier> ]*
none
,此為默認值,表示不引用任何動畫。<identifier>
,引用由@keyframes
定義的動畫名稱。說到這個animation-name
屬性,那就不得不說一下@keyframes
的相關(guān)知識。
@keyframes
@keyframes
用于定義動畫的各個狀態(tài),我們一般稱之為關(guān)鍵幀。其寫法非常自由。其一般的寫法如下,
@keyframes rainbow {
0% { background: #c00 }
50% { background: orange }
100% { background: yellowgreen }
}
animation
引用。0%
~100%
自定義動畫的各個狀態(tài)。其中0%
表示初始狀態(tài),100%
表示結(jié)束狀態(tài)。from
來代替0%
表示初始狀態(tài),可以用to
關(guān)鍵字來代替100%
表示結(jié)束狀態(tài)。animation-timing-function
屬性)。@keyframes moonline {
0% {
top:220px;
left:30%;
opacity:0;
}
30%, 50%, 80% {
top:100px;
left:50%;
opacity:1;
}
100% {
top:220px;
left:80%;
opacity:0;
}
}
animation-duration
animation-duration
意為動畫持續(xù)時間,跟之前的transition-duration
的含義一致。
其語法如下,
animation-duration:<time> [ , <time> ]*
s
),其默認值為0。animation-timing-function
animation-timing-function
用于設(shè)置動畫的速率類型。這個屬性與transition-timing-function
基本一致。
其語法如下,
transition-timing-function:linear | ease | ease-in | ease-out | ease-in-out | step-start | step-end | steps(<integer>[, [ start | end ] ]?) | cubic-bezier
具體的解釋這里就不再贅述了,可參考transition-timing-function
。
animation-delay
animation-delay
用于設(shè)置動畫開始的延時。此屬性與transition-delay
基本一致,請參考transition-delay
的相關(guān)說明。
animation-iteration-count
此屬性用于設(shè)置動畫的循環(huán)次數(shù)。其語法如下,
animation-iteration-count:infinite | <number> [ , infinite | <number> ]*
<integer>
,明確標示動畫的循環(huán)次數(shù)。默認值為1,即動畫只運行一次。infinite
,表示動畫將運行無限次。animation-direction
簡單來說,此屬性用于設(shè)置動畫在循環(huán)運行過程中是否允許反向運動。這啥意思呢?
我們知道當動畫循環(huán)運行時,一次運行周期為:從初始狀態(tài)到結(jié)束狀態(tài)的平滑過渡。一次運行周期結(jié)束后,元素再次下一個周期,即又從初始狀態(tài)平滑過渡到結(jié)束狀態(tài)。我們可以利用animation-direction
屬性改變動畫運行偶數(shù)周期的行為。
此參數(shù)的語法如下,
animation-direction:normal | alternate | reverse | alternate-reverse
normal
,表示使用默認的行為,不作任何改變。alternate
,允許動畫在偶數(shù)周期期間,讓元素從結(jié)束狀態(tài)平滑過渡到初始狀態(tài)。reverse
,動畫的所有運行周期中,讓元素從結(jié)束狀態(tài)平滑過渡到初始狀態(tài)。alternate-reverse
,動畫的奇數(shù)周期內(nèi)過渡方向與設(shè)置的方向相反,偶數(shù)周期內(nèi)過渡方向與設(shè)置的方向相同。這四個預(yù)定義值,一般比較常用的是normal
和alternate
。下面是一個例子,
@keyframes rainbow {
0% {
background-color: yellow;
}
100% {
background: blue;
}
}
.demo:hover {
animation: 1s rainbow 3 normal;
}
.demo2:hover {
animation: 1s rainbow 3 alternate;
}
.demo3:hover {
animation: 1s rainbow 3 reverse;
}
.demo4:hover {
animation: 1s rainbow 3 alternate-reverse;
}
其效果如下,
本demo來自CSS動畫簡介。
animation-play-state
語法如下,
animation-play-state:running | paused [, running | paused]*
running
(運動狀態(tài))和paused
(暫停狀態(tài))。其中running
為默認值。下面讓我們來看一個例子。
div {
trueanimation: spin 2s linear infinite;
trueanimation-play-state: paused;
}
div:hover {
animation-play-state: running;
}
@keyframes spin {
from {
transform: rotate(0deg);
true}
trueto {
true transform: rotate(360deg);
true}
}
具體的效果請參見這個demo。
animation-fill-mode
此屬性用于設(shè)置動畫時間之外元素的狀態(tài)。這里的動畫時間之外可能包括動畫開始運行之前、動畫結(jié)束運行之后、動畫暫停運行時。
其語法如下,
animation-fill-mode:none | forwards | backwards | both
none
,此為默認值,意為不設(shè)置動畫之外的狀態(tài)。forwards
,設(shè)置狀態(tài)為動畫結(jié)束時的狀態(tài)。backwards
,設(shè)置狀態(tài)為動畫開始時的狀態(tài)。both
,設(shè)置狀態(tài)為動畫結(jié)束或開始的狀態(tài)。當循環(huán)運行動畫時,both
會更具根據(jù)animation-direction
輪流應(yīng)用forwards
和backwards
規(guī)則。詳情可參考這個demo。
animation
總結(jié)其實animation
可以說是transition
的進階版本。transition
針對元素的某一個(或者某幾個)特定的css屬性進行過渡,而animation
可以針對元素在過渡期間自定義任意一幀的狀態(tài)。如果不考慮低版本瀏覽器的兼容性,使用css動畫來提升用戶體驗是一種非常好得方式,
個人感覺,從某種意義上來說,設(shè)計師是決定用戶體驗的第一道門檻,CSS的相關(guān)內(nèi)容都是實現(xiàn)。在實際的工作中,我們可以發(fā)揮自己的想象力,使用css動畫的相關(guān)知識,組合各種效果。
更多建議: