CSS animation 動畫

animation 可以建立更複雜的動畫效果,比 transition 更靈活,可以控制關鍵影格、重複次數、方向等。

@keyframes 定義動畫

使用 @keyframes 定義動畫的關鍵影格:

@keyframes 動畫名稱 {
  from {
    /* 起始狀態 */
  }
  to {
    /* 結束狀態 */
  }
}

或使用百分比指定多個關鍵影格:

@keyframes bounce {
  0% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-20px);
  }
  100% {
    transform: translateY(0);
  }
}

套用動畫

.box {
  animation: bounce 1s ease infinite;
}

animation 子屬性

animation-name

指定要使用的動畫名稱。

.box {
  animation-name: bounce;
}

animation-duration

動畫持續時間。

.box {
  animation-duration: 1s;
  animation-duration: 500ms;
}

animation-timing-function

動畫的速度曲線。

.box {
  animation-timing-function: ease;         /* 預設 */
  animation-timing-function: linear;
  animation-timing-function: ease-in;
  animation-timing-function: ease-out;
  animation-timing-function: ease-in-out;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
  animation-timing-function: steps(4);
}

animation-delay

動畫開始前的延遲時間。

.box {
  animation-delay: 0.5s;
  animation-delay: -0.5s;    /* 負值會讓動畫從中間開始 */
}

animation-iteration-count

動畫重複次數。

.box {
  animation-iteration-count: 1;          /* 預設,執行 1 次 */
  animation-iteration-count: 3;          /* 執行 3 次 */
  animation-iteration-count: infinite;   /* 無限重複 */
}

animation-direction

動畫播放方向。

.box {
  animation-direction: normal;            /* 預設,正向播放 */
  animation-direction: reverse;           /* 反向播放 */
  animation-direction: alternate;         /* 正向、反向交替 */
  animation-direction: alternate-reverse; /* 反向、正向交替 */
}

animation-fill-mode

動畫結束後的狀態。

.box {
  animation-fill-mode: none;       /* 預設,回到初始狀態 */
  animation-fill-mode: forwards;   /* 保持在最後一個影格 */
  animation-fill-mode: backwards;  /* 在延遲期間套用第一個影格 */
  animation-fill-mode: both;       /* 同時套用 forwards 和 backwards */
}

animation-play-state

控制動畫播放或暫停。

.box {
  animation-play-state: running;   /* 播放(預設) */
  animation-play-state: paused;    /* 暫停 */
}

/* 常用於 hover 暫停動畫 */
.box:hover {
  animation-play-state: paused;
}

animation 縮寫

/* animation: name duration timing-function delay iteration-count direction fill-mode; */

.box {
  animation: bounce 1s ease 0s infinite alternate forwards;
}

/* 簡化 */
.box {
  animation: bounce 1s infinite;
}

多個動畫

用逗號分隔套用多個動畫:

.box {
  animation: 
    bounce 1s ease infinite,
    fade 2s ease-in-out infinite alternate;
}

實用範例

淡入

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.fade-in {
  animation: fadeIn 0.5s ease forwards;
}

從下滑入

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.slide-up {
  animation: slideUp 0.5s ease forwards;
}

脈動效果

@keyframes pulse {
  0%, 100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.05);
  }
}

.pulse {
  animation: pulse 2s ease-in-out infinite;
}

旋轉載入

@keyframes spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.spinner {
  animation: spin 1s linear infinite;
}

彈跳效果

@keyframes bounce {
  0%, 100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-15px);
  }
}

.bounce {
  animation: bounce 0.6s ease infinite;
}

搖晃效果

@keyframes shake {
  0%, 100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-5px);
  }
  75% {
    transform: translateX(5px);
  }
}

.shake {
  animation: shake 0.5s ease;
}

閃爍效果

@keyframes blink {
  0%, 100% {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

.blink {
  animation: blink 1s step-end infinite;
}

打字效果

@keyframes typing {
  from {
    width: 0;
  }
  to {
    width: 100%;
  }
}

@keyframes cursor {
  50% {
    border-color: transparent;
  }
}

.typewriter {
  overflow: hidden;
  white-space: nowrap;
  border-right: 2px solid black;
  animation: 
    typing 3s steps(30) forwards,
    cursor 0.5s step-end infinite;
}

交錯動畫

.item {
  animation: fadeIn 0.5s ease forwards;
  opacity: 0;
}

.item:nth-child(1) { animation-delay: 0.1s; }
.item:nth-child(2) { animation-delay: 0.2s; }
.item:nth-child(3) { animation-delay: 0.3s; }
.item:nth-child(4) { animation-delay: 0.4s; }

效能建議

  • 優先動畫 transformopacity
  • 避免動畫會觸發重排的屬性(width、height、margin 等)
  • 使用 will-change 提示瀏覽器優化
.animated {
  will-change: transform, opacity;
}

尊重使用者偏好

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}