Design

微互動的 12 個經典場景:60 分到 90 分的 UI 細節

2026 年 5 月 5 日約 9 分鐘閱讀作者:Hao0321 Studio

網站做完功能只是 60 分。剩下 30 分藏在「微互動」裡 — 那些使用者察覺不到但能感受到的小動畫、即時回饋、狀態變化。這篇整理 12 個經典場景,每個附 CSS / JS 範例。

1. Hover:尺寸放大 + 陰影加深

.card {
  transition: all 0.25s cubic-bezier(0.22, 1, 0.36, 1);
}
.card:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 32px rgba(15,15,30,0.08);
}

關鍵是 cubic-bezier(0.22, 1, 0.36, 1)。這條曲線比 ease-out 更自然,前段快、後段緩。Linear 動畫看起來機械,這條曲線看起來「物理感」。

2. 按鈕點擊:scale down 0.97

button {
  transition: transform 0.1s;
}
button:active {
  transform: scale(0.97);
}

0.1s 才有「真的被按下」的觸覺感。0.3s 太慢、0.05s 太快感覺不到。

3. Loading 狀態:skeleton 取代 spinner

白色閃光從左滑到右,比旋轉的 spinner 更降低焦慮感:

.skeleton {
  background: linear-gradient(90deg, #f0f0f0, #e0e0e0, #f0f0f0);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
  0% { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

4. 表單驗證:邊框顏色 + 圖示

不要等 submit 才告訴使用者錯。輸入完離開欄位(blur)就驗證:

input.invalid { border-color: #e11d48; }
input.valid { border-color: #15803d; }
input:focus { outline: 2px solid var(--accent-blue); }

5. Modal 開啟:fade + scale

.modal {
  opacity: 0;
  transform: scale(0.95);
  transition: opacity 0.2s, transform 0.2s;
}
.modal.open {
  opacity: 1;
  transform: scale(1);
}

scale 從 0.95 到 1 模擬「從遠處 zoom in」的感覺。比直接跳出更有層次。

6. 滾動觸發:IntersectionObserver + 淡入

const io = new IntersectionObserver(entries => {
  entries.forEach(e => {
    if (e.isIntersecting) e.target.classList.add('in-view');
  });
}, { threshold: 0.15 });
document.querySelectorAll('.reveal').forEach(el => io.observe(el));

/* CSS */
.reveal { opacity: 0; transform: translateY(20px); transition: 0.8s; }
.reveal.in-view { opacity: 1; transform: translateY(0); }

7. 數字滾動 (counter)

從 0 滑到目標數字,比直接顯示更有衝擊:

function animateCount(el, target, duration = 1500) {
  const start = performance.now();
  function step(now) {
    const p = Math.min((now - start) / duration, 1);
    const eased = 1 - Math.pow(1 - p, 3);
    el.textContent = Math.round(eased * target);
    if (p < 1) requestAnimationFrame(step);
  }
  requestAnimationFrame(step);
}

8. Toast 通知:從上方滑入 + 自動消失

.toast {
  transform: translateY(-100%);
  transition: transform 0.3s;
}
.toast.show {
  transform: translateY(0);
}

9. 切換主題:crossfade 整頁

html.theme-transitioning * {
  transition: background-color 0.3s, color 0.3s, border-color 0.3s !important;
}

暫時加個 class 讓所有元素都有 transition,切換完移除,避免後續操作都很慢。

10. 卡片進場:staggered animation

多個卡片不要同時出現,差 50ms 一個:

.card:nth-child(1) { animation-delay: 0ms; }
.card:nth-child(2) { animation-delay: 50ms; }
.card:nth-child(3) { animation-delay: 100ms; }

創造「依序出現」的節奏感,比一次彈出去自然。

11. 拖曳 (drag):透明度 + 旋轉

拖曳時稍微透明 + 微旋轉,給予「正在拖」的明確感受:

.dragging {
  opacity: 0.7;
  transform: rotate(-2deg);
  cursor: grabbing;
}

12. Form Submit:按鈕 → loading → success

三段狀態切換:

<button class="btn-submit">
  <span class="label">提交</span>
  <span class="spinner">⌛</span>
  <span class="check">✓</span>
</button>
.btn-submit.loading .label { opacity: 0; }
.btn-submit.loading .spinner { opacity: 1; }
.btn-submit.success .check { opacity: 1; }

原則總結

原則應用
動畫不超過 300ms使用者注意力短,過久反而煩
用 cubic-bezier 不用 linear自然物理感
狀態切換要可逆不要只有「開」沒有「關」動畫
尊重 prefers-reduced-motion無障礙考量
過度動畫 = 無動畫節奏感比花哨重要

結語

使用者通常記不住網站視覺,但會記住「感覺好用」。這些微互動就是「感覺好用」的來源。每個都只是 5–10 行 CSS,組合起來決定一個網站的質感。