Skip to main content

CSS3 轉場效果

/* 哪個物件要執行動畫 */
animation: 動畫名稱 播放時間 速度函式 延遲播放時間 次數 方向 填充模式

/* 細項全名 */
animation-name: my-animation; // 動畫名稱,可以用逗號套用多個 @keyframes
animation-duration: 1s; // 播放時間
animation-timing-function: linear | ease-in-out; // 速度函式
animation-delay: 0.5s; // 延遲多久開始執行
animation-iteration-count: infinite | number; // 播放次數
animation-direction: normal | alternate (來回播放) |
reverse(從 100% 跑回 0 %) | alternate-reverse; // 方向
animation-fill-mode: none | forwards | backwards | both; // 填充模式,動畫執行前後,目標如何套用 CSS Animation
animation-play-state: paused | running; // 定義動畫執行或停止

/* 動畫內容 */
@keyframes 動畫名稱 {
0%{...}
100%{...}
}

CSS 動畫指的是使用以 CSS 定義為主的動畫效果,又可以分成以下兩類:

  • CSS3 轉場/過渡(transitions)
    • 主要以開始狀態、結束狀態與持續期間(duration)三種參數,以及可指定的漸變函數(transition timing function),將 DOM 元素或網頁上的物件進行轉變。
  • CSS3 動畫(animations)
    • 又稱為關鍵影格(Keyframe)動畫,可以加入關鍵影格,提供許多動畫片段的組合。

以 CSS 定義為主的動畫相較於使用 JavaScript 程式為主的動畫有一些好處:

  • 簡單,對於一些簡單的動畫特效,不需要撰寫程式就可以製作出動畫。
  • 低消費,對於電腦資源的消耗非常低。
  • 最佳化,瀏覽器對於 CSS 動畫可以提供最佳化,動畫可以運作得相當順暢。

CSS3 轉場與 CSS3 動畫的"相同"之處

  • 都是使用 CSS 定義,然後監聽 DOM 元素的改變作出動畫效果
  • 都可以設定漸變函數(transition timing function),控制動畫的運動(效果展現)的曲線
  • 都可以設定持續期間(duration),控制動畫持續的時間
  • 都有對應的 event(事件),可以送出動畫的狀態,可讓 JavaScript 再加以監聽或控制(可程式化)
  • 都可以用視覺化方式看到 CSS 屬性正在改變的狀態

CSS3 轉場與 CSS3 動畫的"不同"之處

觸發(Trigger)方式

轉場(transitions)觸發使用:hover僞(pseudo)類別為最經常使用,其他可觸發的還有:active:focus:checked等等,另一種方式是使用 JavaScript 語言動態加入或移除 CSS 類別,更多範例可以參考這一篇範例

動畫(animations)不需要觸發,當你定義好後,頁面一載入就會開始進行動畫。

循環/重覆播放(Looping)

轉場(transitions)沒有指定循環播放的屬性可用。

動畫(animations)有animation-iteration-count屬性可指定循環播放的次數,或是用"infinite"指定為不停地重覆播放。

定義關鍵影格(Keyframes)/中途點

轉場(transitions)沒有這特性。動畫的撥放就是從開始到結束。

動畫(animations)可以額外定義關鍵影格(Keyframes),可以製作更複雜的動畫效果。

註: 有一個常會搞混的transform的 CSS 的新屬性,它可以把網頁上的物件或元素進行變形、翻轉或 2d 與 3d 的效果,它並不是與動畫有關的屬性,你可以把它當成是類似字體顏色大小、透明度(opacity)的屬性。也可以搭配 CSS 動畫來使用。

搭配 JavaScript 互動的混合作法

轉場(transitions)很容易可以搭配 JavaScript 程式作額外的互動應用。

動畫(animations)比較不容易,但仍然是可以搭配 JavaScript 使用。

Transitions 轉場

在 CSS3 之前的轉場特效,都是立即完成的,轉場特效提供了更為豐富的動畫效果,以下為本章用來說明的一個簡單範例:

.box {
background: #2db34a;
border-radius: 6px;
height: 95px;
width: 95px;
}

.box:hover {
background: #ff2956;
}

下面是我們的第一個範例,左邊的是用上面的定義的方形,右邊的有另外加一行transition: 1s;的定義,它會在滑鼠游標在上面時,出現轉場效果,滑鼠游標移開後會回復原來的屬性,你可以比對看看兩者的不同。

轉場特效使用四個 CSS 屬性來進行定義,這些屬性可以整個合併到一個transition屬性之中:

  • transition-property: 定義哪些 CSS 屬性會被轉場效果影響。除了這些被指定的屬性,其他的轉場一如以往的會在瞬間完成。要特別注意的是,並非所有的 CSS 屬性都可以進行轉場,可用的屬性所有清單在這份資料可進行動畫屬性,其中也包含了 SVG 的屬性。如果這個屬性定義為transform,代表任何使用了transform的屬性都會被偵測來進行動畫。如果這個屬性定義為all,就會自動偵測所有可進行動畫的屬性,包含transform影響的屬性。預設值就是all
  • transition-duration: 定義轉場的持續時間。可以只定義一個時間給所有屬性使用,也可以分別給定不同時間。時間通常以s為單位(秒),可以定義小數點例如0.5s.5s,預設值是0s
  • transition-timing-function: 時間函式,這是用來設定轉場過程時所使用的貝茲曲線。內建的幾個可直接使用數值如下,直接使用名稱就可以取用。在這個頁面中看到所有的預設值的範例:
    • ease
    • linear
    • ease-in
    • ease-out
    • ease-in-out
    • step-start
    • step-end
    • steps()
    • cubic-bezier()

其中cubic-bezier()的數值,可以到cubic-bezier.com來自訂所需要的貝茲曲線參數值,或是到這一頁Easing 函數CSS EASING ANIMATION TOOL的裡面挑選你想要的 Easing 函數,使用四個數字值可以產生一個貝茲曲線。預設值是ease

  • transition-delay: 定義多久之後開始發生轉場,這是一個延遲開始的時間。時間通常以s為單位(秒),可以定義小數點例如0.5s.5s,預設值是0s

transition屬性的合併寫法是按照上面的順序依次寫成一整行,所以如果都是以預設值來寫 CSS 定義的話,可以用非常簡單的寫法像這樣:

transition: .5s;

相當於下面這樣,第 1、3、4 值都是使用預設值。而.5s代表的是持續期間(duration),而且因為最後面的那個延遲開始(delay)的預設值是 0s,一般都不寫:

transition: all .5s ease;

註: 雖然你可以用ms(微秒,千分之一秒)為單位來設定持續與延遲開始時間,但似乎不必要,因為太短暫的時間差人眼無法感覺差異。

順序口訣: 屬性的順序的口訣,例如"屬持茲遲"(手持支援)或"屬續貝延"(手續被延期)

你也可以為每個不同的 CSS 屬性分別設定轉場的動畫定義:

.box {
background: #2db34a;
border-radius: 6px;
height: 95px;
width: 95px;

-webkit-transition: background 0.2s linear, border-radius 1s ease-in 1s;
transition: background 0.2s linear, border-radius 1s ease-in 1s;
}

.box:hover {
background: #ff2956;
border-radius: 50%;
}

以下為這個範例的執行結果,你可以把滑鼠游標放在上面久一點,因為第二個屬性(圓角邊)會在 1s 後才延遲開始。

轉場特效的概念十分簡單,開始狀態、結束狀態,以及持續時間、轉場使用的貝茲曲線函式。對滑鼠滑入(hover)來說,.box是開始狀態,而.box:hover是結束狀態。但當滑鼠游標離開時,就會兩個顛倒過來。那到底transition該加在.box中還是.box:hover中?大部份的情況是只需要加在.box中,除非你希望滑鼠游標移入與離開是兩種不同的轉場特效情況,不過你需要把所有的屬性都對應好,不然會產生立即執行的失效情況。如果你只加在:hover 中大概是錯誤的寫法。以下為範例:

供應商前綴字(Vendor Prefixes)

供應商前綴字的出現是由於瀏覽器不同品牌的廠商,搶先於標準完成前就開始發佈已包含實作功能造成的結果。因為這些 CSS 屬性有可能在瀏覽器中有可能是屬於實驗性質的,所以在前面加上了瀏覽器供應商的前綴字,代表是要開啟這個實驗性的 CSS 屬性,到後來變成一個要為了相容不同瀏覽器的特殊寫法。而且,這不只是針對 CSS3 動畫相關的屬性,在一些新式的屬性,例如陰影或漸層,都有需要使用供應商前綴字的情況。由於瀏覽器新版本都自動偵測支援,現在這個問題會比較少見了。

不過,要記住哪一些屬性是需要加供應商前綴字,哪一些則不用,這是件非常令人頭痛的事情。一般都會使用一種叫 Autoprefixer(自動前綴字產生器)的工具來幫忙轉換,例如下面的工具:

現在一般來說只需要加上-webkit-前綴字即可,例如以下的範例:

-webkit-transition: background .2s linear, border-radius 1s ease-in 1s;
transition: background .2s linear, border-radius 1s ease-in 1s;

Animation 動畫

快束了解 CSS animation

/* 哪個物件要執行動畫 */
animation: 動畫名稱 播放時間 速度函式 延遲播放時間 次數 方向 填充模式

/* 細項全名 */
animation-name: my-animation; /* 動畫名稱,可以用逗號套用多個 @keyframes */
animation-duration: 1s; /* 播放時間 */
animation-timing-function: linear | ease-in-out; /* 速度函式 */
animation-delay: 0.5s; /* 延遲多久開始執行 */
animation-iteration-count: infinite | number; /* 播放次數 */
animation-direction: normal | alternate (來回播放) |
reverse(從 100% 跑回 0 %) | alternate-reverse; // 方向
animation-fill-mode: none | forwards | backwards | both; // 填充模式,動畫執行前後,目標如何套用 CSS Animation
animation-play-state: paused | running; // 定義動畫執行或停止

/* 動畫內容 */
@keyframes 動畫名稱 {
0%{...}
100%{...}
}

動畫的基礎定義

動畫的這三個屬性,持續期間、時間函式與延遲開始時間,這部份的內容與 CSS3 轉場一模一樣:

  • animation-duration

    • 持續期間。時間通常以s為單位(秒),可以定義小數點例如0.5s.5s,預設值是0s
  • animation-timing-function

    • 時間函式,這是用來設定轉場過程時所使用的貝茲曲線,預設值是ease
  • animation-delay

    • 延遲開始時間。時間通常以s為單位(秒),可以定義小數點例如0.5s.5s,預設值是0s

但與轉場不同的是,轉場使用的第 1 個屬性是用transition-property直接定義要進行轉場的屬性,而動畫是使用animation-name定義一組名稱。

這個名稱是對應到關鍵影格@keyframes的規則(rule)的名稱,一個最簡單的@keyframes規則如下,0%代表第一個關鍵影格,也就是開始的狀態,也可以使用from代表。100%則是最後一個關鍵影格,結束的狀態,也可以使用to代表,中間的部份依照不同的時期可以用百分比來表示,這是依照你的持續時間來分割的:

@keyframes pinpon {
0% {
left: 0;
top: 0;
}
50% {
left: 200px;
top: 150px;
}
100% {
left: 300px;
top: 0;
}
}

對照的 CSS3 其他定義值如下,可以看到這裡的animation-name指定為上面的"pinpon"關鍵影格名稱:

animation-name: pinpon;
animation-duration: 3s;
animation-timing-function: ease-in;
animation-delay: 1s;

下面是這個範例的執行結果,它是一載入頁面立即執行的,如果看不到請重新載入範例的頁面。這是動畫的特性,不過也有另外可以讓它用類似轉場的觸發方式來執行,後面會再提到。

其他更多的屬性

動畫還有其他一些不同的屬性可以進行定義,以下列出來:

  • animation-iteration-count(播放循環次數): 用於設定動畫播放次數,預設是 1,可以設定正整數,例如 5。或帶有小數點的小數,例如 0.5 代表播放半次。infinite代表永不停止的播放。
  • animation-direction(播放方向): 用於定義播放的方向,有以下幾種值可以使用:
    • normal(正常)
    • reverse(反向/倒帶)
    • alternate(輪流)
    • alternate-reverse(輪流與反向)

運用這兩個屬性,可以把上面的範例再調整一下,讓球的運動可以來回不斷的跳動,例如以下的範例:

  • animation-fill-mode(播放後樣式): 指的是動畫播放後的樣式,是不是要保留在最後的狀態。預設值是none,設定為forwards會停留在最後的樣式,backwards則是一開始的樣式。both是兩者都套用。這個值會因為animation-direction屬性的方向值而有不同的套用對象。

下面的範例是使用forwards來指定,最後會停留在最後套用的樣式。

  • animation-play-state(播放狀態): 這個屬性可以控制動畫播放的暫停,預設是running,可以設為paused來暫停播放。

下面的範例是使用:hover加上paused,滑鼠游標放在球上面,動畫就會暫停,游標移出後又會繼續。

簡寫語法(整合語法)

由於 animation 的屬性有 8 個之多,要使用簡寫的方式把所有的屬性寫成一行會比較不容易。以下列出所有的屬性順序與其預設值:

animation-name: none
animation-duration: 0s
animation-timing-function: ease
animation-delay: 0s
animation-iteration-count: 1
animation-direction: normal
animation-fill-mode: none
animation-play-state: running

順序口訣: 名詞支援次方"填充""狀態" - 名稱、持續、貝茲、延遲、次數、方向、填充(最後樣式)、狀態(暫停/執行)

在簡寫語法中,名稱(animation-name)可以放在第一個值,也可以放在最後一個值,例如像下面這些寫法中的slidein實際上是@keyframes的規則的名稱:

/* @keyframes duration | timing-function | delay |
iteration-count | direction | fill-mode | play-state | name */
animation: 3s ease-in 1s 2 reverse both paused slidein;

/* @keyframes duration | timing-function | delay | name */
animation: 3s linear 1s slidein;

/* @keyframes duration | name */
animation: 3s slidein;

供應商前綴字(Vendor Prefixes)

與轉場相同,CSS3 動畫屬性也有供應商前綴字的問題,現在一般來說只需要加上-webkit-前綴字即可。可以使用以下的工具來協助加上:

使用:hover來觸發動畫

下面的範例可以用一個外圍的 div 元素來框住進行 CSS3 動畫的球元素,讓它在滑鼠游標移入在上面時才開始進行動畫,按住滑鼠左鍵時可以暫停動畫。但你應該發現不論如何,使用 CSS3 動畫是無法在播放期間直接中止的。

參考文章