Deepen PracticeOrdered learning track

Transitions, Animations, Motion Design, and Reduced Motion

Part 24 — Transitions, Animations, Motion Design, and Reduced Motion

Belajar CSS transitions, animations, transform, easing, motion tokens, prefers-reduced-motion, accessibility, performance rendering, dan pola motion design yang aman untuk UI production.

12 min read2368 words
PrevNext
Lesson 2432 lesson track1927 Deepen Practice
#html#css#transitions#animations+6 more

Part 24 — Transitions, Animations, Motion Design, and Reduced Motion

Motion di UI bukan hiasan. Motion adalah feedback system.

Motion yang baik membantu user memahami:

  • sesuatu berubah,
  • action diterima,
  • elemen muncul/hilang,
  • fokus berpindah,
  • proses sedang berlangsung,
  • hierarchy atau relationship antar elemen.

Motion yang buruk membuat UI terasa lambat, mengganggu, memicu motion sickness, atau menyembunyikan state yang seharusnya jelas.

Part ini membahas CSS transition dan animation sebagai interaction contract: kapan dipakai, apa yang aman dianimasikan, bagaimana menghindari jank, dan bagaimana menghormati user yang memilih reduced motion.


1. Target Skill

Setelah menyelesaikan part ini, kamu harus bisa:

  • membedakan transition, animation, transform, dan JavaScript-driven animation,
  • memilih property yang aman dianimasikan,
  • memahami hubungan animation dengan rendering pipeline,
  • membuat hover/focus/active feedback yang tidak mengganggu,
  • membuat dialog/popover/toast masuk dan keluar dengan jelas,
  • membuat loading/skeleton state yang tidak menipu,
  • memakai prefers-reduced-motion secara benar,
  • membuat motion tokens untuk duration/easing/distance,
  • menghindari animation yang menyebabkan layout shift atau motion sickness,
  • men-debug animation performance di browser DevTools.

Target akhirnya: kamu bisa membuat motion yang purposeful, accessible, performant, dan maintainable.


2. Kaufman Deconstruction

Untuk latihan awal, jangan membuat animasi kompleks. Mulai dari:

  • button state,
  • focus state,
  • disclosure expand/collapse,
  • modal enter/exit,
  • toast notification,
  • skeleton/loading indicator,
  • reduced-motion fallback.

3. Motion sebagai State Communication

Motion harus menjawab salah satu pertanyaan user:

  • “Apakah klik saya diterima?”
  • “Apa yang baru muncul?”
  • “Ke mana elemen itu pergi?”
  • “Apakah proses masih berjalan?”
  • “Apakah ini state berbeda?”

Jika motion tidak menjawab pertanyaan, mungkin ia hanya noise.

Contoh motion yang punya purpose:

.button {
  transition:
    background-color 150ms ease,
    border-color 150ms ease,
    transform 100ms ease;
}

.button:hover {
  background: var(--color-bg-action-hover);
}

.button:active {
  transform: translateY(1px);
}

Klik memberi tactile feedback ringan. Tidak ada gerakan besar, tidak mengubah layout, dan durasinya singkat.


4. Transition vs Animation

Gunakan transition ketika perubahan dipicu oleh perubahan state dan browser bisa interpolate dari nilai awal ke nilai akhir.

Contoh:

.card {
  border-color: var(--color-border-subtle);
  box-shadow: none;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}

.card:hover {
  border-color: var(--color-border-strong);
  box-shadow: var(--shadow-sm);
}

Gunakan animation ketika kamu butuh sequence yang tidak sekadar state A ke state B.

Contoh:

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

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

Rule praktis:

KebutuhanMekanisme
hover/focus/active statetransition
menu/dialog entertransition atau animation sederhana
loading indicatoranimation
repeated attention cueanimation, hati-hati
route/page transitionView Transitions/JS/CSS, tergantung architecture
physics/drag gestureJavaScript/Web Animations API

5. Transition Anatomy

Properti penting:

.element {
  transition-property: opacity, transform;
  transition-duration: 180ms;
  transition-timing-function: ease-out;
  transition-delay: 0ms;
}

Shorthand:

.element {
  transition:
    opacity 180ms ease-out,
    transform 180ms ease-out;
}

Hindari:

.element {
  transition: all 300ms ease;
}

Mengapa?

  • property yang tidak dimaksud bisa ikut dianimasikan,
  • debugging lebih sulit,
  • future CSS change bisa menyebabkan animasi aneh,
  • property layout seperti width, height, margin, top, left bisa ikut berubah dan memicu jank.

Gunakan property eksplisit.


6. Animatable Properties dan Rendering Cost

Tidak semua property sama biayanya.

Mental model rendering:

Property yang umumnya lebih aman untuk animation:

  • transform,
  • opacity.

Property yang sering mahal:

  • width, height,
  • margin, padding,
  • top, right, bottom, left,
  • font-size,
  • box-shadow besar/kompleks,
  • filter,
  • properties yang memicu repaint besar.

Catatan: “transform/opacity selalu gratis” juga mitos. Mereka lebih mudah di-composite, tetapi terlalu banyak layer, gambar besar, blur/filter, atau animasi fullscreen tetap bisa mahal.


7. Transform Fundamentals

transform mengubah coordinate space visual elemen tanpa mengubah layout normal flow.

Contoh:

.popover {
  opacity: 0;
  transform: translateY(-0.25rem) scale(0.98);
  transition:
    opacity 120ms ease,
    transform 120ms ease;
}

.popover[data-open="true"] {
  opacity: 1;
  transform: translateY(0) scale(1);
}

Transform umum:

.item { transform: translateX(1rem); }
.item { transform: translateY(-0.25rem); }
.item { transform: scale(0.98); }
.item { transform: rotate(2deg); }

Modern CSS juga punya individual transform properties:

.item {
  translate: 0 -0.25rem;
  scale: 0.98;
}

Namun untuk compatibility strategy, cek Baseline/support sebelum memilih individual properties sebagai default.


8. Opacity

opacity berguna untuk fade in/out.

.toast {
  opacity: 0;
  transform: translateY(var(--space-2));
  transition: opacity 180ms ease, transform 180ms ease;
}

.toast[data-visible="true"] {
  opacity: 1;
  transform: translateY(0);
}

Hati-hati: opacity: 0 hanya membuat elemen transparan. Elemen masih bisa berada di accessibility tree dan bisa menerima pointer/focus tergantung property lain.

Untuk hidden state:

.toast[hidden] {
  display: none;
}

Untuk transisi exit, biasanya butuh koordinasi state dari JavaScript atau API seperti @starting-style/popover/dialog transition pattern. Jangan mengandalkan opacity saja untuk menyembunyikan konten interaktif.


9. Duration

Duration harus pendek untuk micro-interaction.

Practical default:

:root {
  --duration-instant: 0ms;
  --duration-fast: 100ms;
  --duration-normal: 180ms;
  --duration-slow: 280ms;
  --duration-slower: 400ms;
}

Mapping:

InteractionDuration umum
button active press75–120ms
hover color120–180ms
tooltip/popover enter120–200ms
dialog enter180–280ms
large page transition250–400ms
loading pulse900–1600ms loop

Jangan membuat user menunggu animasi. Motion harus membantu memahami state, bukan memblokir pekerjaan.


10. Easing

Easing menentukan rasa gerakan.

Token:

:root {
  --ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --ease-enter: cubic-bezier(0, 0, 0, 1);
  --ease-exit: cubic-bezier(0.4, 0, 1, 1);
  --ease-emphasized: cubic-bezier(0.2, 0, 0, 1);
}

Rule praktis:

  • enter: cepat selesai, terasa ringan,
  • exit: boleh sedikit lebih cepat,
  • hover/focus: simple ease cukup,
  • destructive/error motion: jangan playful,
  • enterprise UI: prioritaskan clarity dibanding theatrical motion.

11. Motion Tokens

Buat motion system seperti color/spacing system.

:root {
  --motion-duration-fast: 100ms;
  --motion-duration-normal: 180ms;
  --motion-duration-slow: 280ms;

  --motion-ease-standard: cubic-bezier(0.2, 0, 0, 1);
  --motion-ease-enter: cubic-bezier(0, 0, 0, 1);
  --motion-ease-exit: cubic-bezier(0.4, 0, 1, 1);

  --motion-distance-sm: 0.25rem;
  --motion-distance-md: 0.5rem;
}

Component menggunakan token:

.menu {
  opacity: 0;
  transform: translateY(calc(-1 * var(--motion-distance-sm)));
  transition:
    opacity var(--motion-duration-fast) var(--motion-ease-enter),
    transform var(--motion-duration-fast) var(--motion-ease-enter);
}

Keuntungan:

  • konsisten,
  • mudah dikurangi untuk reduced motion,
  • mudah di-review,
  • tidak ada angka animasi acak.

12. Reduced Motion sebagai Requirement, Bukan Bonus

User dapat mengaktifkan setting reduce motion di OS/browser. CSS bisa membaca preferensi ini dengan media feature prefers-reduced-motion.

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
  }
}

Snippet global seperti ini populer, tetapi jangan berhenti di sini. Untuk produk serius, lebih baik desain reduced motion secara semantic.

@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-duration-fast: 0ms;
    --motion-duration-normal: 0ms;
    --motion-duration-slow: 0ms;
    --motion-distance-sm: 0;
    --motion-distance-md: 0;
  }

  .skeleton {
    animation: none;
  }
}

Tujuan reduced motion bukan selalu “hapus semua perubahan visual”. Tujuannya menghapus/mengurangi motion yang tidak diperlukan, terutama motion besar, parallax, zoom, spinning, dan movement yang mengikuti interaksi.


13. WCAG Motion Considerations

WCAG membahas motion dan flashing karena sebagian user dapat terganggu atau terdampak secara fisik oleh animasi tertentu.

Prinsip praktis:

  • motion dari interaksi harus bisa dinonaktifkan kecuali essential,
  • jangan membuat flashing/strobing,
  • jangan pakai motion sebagai satu-satunya cara menyampaikan informasi,
  • jangan membuat animasi yang mengganggu focus/reading,
  • jangan membuat auto-playing motion yang tidak bisa dikontrol.

Untuk engineering review, tanyakan:

  • Apakah animasi ini essential?
  • Apakah ada reduced-motion variant?
  • Apakah informasi tetap jelas tanpa animasi?
  • Apakah keyboard user terkena efek yang sama?
  • Apakah focus berpindah secara predictable?

14. Hover, Focus, Active Feedback

Micro-interaction paling umum:

.interactive-surface {
  transition:
    background-color var(--motion-duration-fast) ease,
    border-color var(--motion-duration-fast) ease,
    box-shadow var(--motion-duration-fast) ease;
}

.interactive-surface:hover {
  background: var(--color-bg-surface-hover);
}

.interactive-surface:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

.interactive-surface:active {
  transform: translateY(1px);
}

@media (prefers-reduced-motion: reduce) {
  .interactive-surface:active {
    transform: none;
  }
}

Catatan: jangan membuat focus indicator bergantung pada transition lambat. Keyboard user perlu feedback langsung.


15. Menu/Popover Enter Motion

Popover sebaiknya muncul cepat, jelas, dan tidak bergerak jauh.

.popover {
  opacity: 0;
  transform: translateY(-0.25rem);
  transform-origin: top;
  transition:
    opacity var(--motion-duration-fast) var(--motion-ease-enter),
    transform var(--motion-duration-fast) var(--motion-ease-enter);
}

.popover[data-open="true"] {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .popover {
    transform: none;
  }
}

Jangan memakai slide 40px untuk popover kecil. Movement terlalu besar membuat UI terasa tidak stabil.


16. Dialog Motion

Dialog punya dua layer: backdrop dan panel.

.dialog-backdrop {
  opacity: 0;
  transition: opacity var(--motion-duration-normal) ease;
}

.dialog-panel {
  opacity: 0;
  transform: translateY(var(--motion-distance-md)) scale(0.98);
  transition:
    opacity var(--motion-duration-normal) var(--motion-ease-enter),
    transform var(--motion-duration-normal) var(--motion-ease-enter);
}

.dialog[data-open="true"] .dialog-backdrop,
.dialog[data-open="true"] .dialog-panel {
  opacity: 1;
}

.dialog[data-open="true"] .dialog-panel {
  transform: translateY(0) scale(1);
}

@media (prefers-reduced-motion: reduce) {
  .dialog-panel {
    transform: none;
  }
}

Motion dialog harus selaras dengan focus management:

  • ketika dialog terbuka, focus masuk ke dialog,
  • background tidak dapat diakses,
  • Escape menutup jika sesuai pattern,
  • setelah close, focus kembali ke trigger.

CSS motion tidak menggantikan accessibility behavior.


17. Toast Notification Motion

Toast harus muncul tanpa mengganggu task utama.

.toast-region {
  position: fixed;
  inset-block-end: var(--space-4);
  inset-inline-end: var(--space-4);
  display: grid;
  gap: var(--space-2);
  inline-size: min(100% - 2rem, 24rem);
}

.toast {
  opacity: 0;
  transform: translateY(var(--motion-distance-md));
  transition:
    opacity var(--motion-duration-normal) ease,
    transform var(--motion-duration-normal) ease;
}

.toast[data-visible="true"] {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .toast {
    transform: none;
  }
}

Untuk accessibility, toast penting harus memakai live region yang tepat. Jangan membuat toast hilang terlalu cepat jika isinya penting.


18. Disclosure / Expand-Collapse

Animating height dari 0 ke auto historically sulit. Banyak implementasi memakai max-height, tetapi itu hack.

Contoh sederhana tanpa animasi height:

.disclosure__panel {
  border-block-start: 1px solid var(--color-border-subtle);
  padding-block-start: var(--space-3);
}

Jika ingin motion, gunakan opacity/transform untuk konten kecil:

.disclosure__panel {
  opacity: 0;
  transform: translateY(-0.25rem);
  transition: opacity 150ms ease, transform 150ms ease;
}

.disclosure[open] .disclosure__panel {
  opacity: 1;
  transform: translateY(0);
}

Namun hati-hati: jika panel masih mengambil layout space, motion ini hanya visual. Untuk expand/collapse yang benar, behavior perlu dipikirkan bersama HTML state.


19. Loading Indicators

Loading indicator harus jujur.

Gunakan spinner untuk durasi tidak diketahui, skeleton untuk konten yang struktur layout-nya sudah diketahui, progress bar untuk progress yang bisa diukur.

Skeleton:

@keyframes skeleton-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

.skeleton {
  border-radius: var(--radius-sm);
  background: var(--color-bg-muted);
  animation: skeleton-pulse 1.2s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  .skeleton {
    animation: none;
  }
}

Jangan membuat skeleton terlalu lama jika data sudah gagal. Loading state harus punya timeout/error state di level aplikasi.


20. Attention Animation

Kadang UI perlu menarik perhatian: error, new item, updated row, successful save.

Gunakan motion ringan dan terbatas.

@keyframes highlight-row {
  from { background-color: var(--color-status-info-bg); }
  to { background-color: transparent; }
}

.row--updated {
  animation: highlight-row 1.2s ease-out 1;
}

@media (prefers-reduced-motion: reduce) {
  .row--updated {
    animation: none;
    outline: 2px solid var(--color-status-info-border);
    outline-offset: -2px;
  }
}

Di reduced motion, ganti temporal movement dengan static indicator.


21. Scroll Behavior

Smooth scroll bisa membantu orientasi, tetapi juga bisa mengganggu user reduced motion.

html {
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
}

Untuk aplikasi enterprise, smooth scroll jangan menyembunyikan error. Jika user submit form dan ada error, pindahkan focus ke error summary atau field pertama yang invalid secara jelas.


22. will-change

will-change memberi hint ke browser bahwa property akan berubah. Ini bukan performance magic.

.popover[data-open="true"] {
  will-change: opacity, transform;
}

Hati-hati:

  • jangan memasang will-change global,
  • jangan dipakai permanen di banyak elemen,
  • terlalu banyak layer bisa meningkatkan memory dan menurunkan performance,
  • gunakan hanya ketika ada bukti perlu.

Default: jangan pakai sampai kamu melihat masalah nyata.


23. Motion dan Layout Shift

Animasi yang mengubah layout bisa menyebabkan elemen lain bergerak.

Buruk:

.sidebar {
  transition: width 250ms ease;
}

.sidebar[data-collapsed="true"] {
  width: 4rem;
}

Jika content utama ikut bergeser, user bisa kehilangan focus.

Alternatif:

  • buat layout state change langsung, tanpa animasi,
  • animasikan transform pada overlay sidebar,
  • gunakan transition hanya untuk opacity/icon label,
  • hormati reduced motion.

Tidak semua perubahan layout perlu dianimasikan.


24. Motion dan State Machine UI

Untuk aplikasi serius, motion harus mengikuti state machine.

Masalah umum:

  • user klik open lalu close sebelum animation selesai,
  • component unmount sebelum exit animation selesai,
  • focus pindah sebelum dialog benar-benar siap,
  • display: none diterapkan terlalu cepat,
  • animationend tidak terpanggil karena reduced motion atau tab background.

Jika framework JS dipakai, state visual harus sinkron dengan state accessibility.


25. CSS-Only State vs Application State

CSS cocok untuk:

  • hover,
  • focus,
  • active,
  • simple transition,
  • media preference,
  • visual feedback lokal.

Application state diperlukan untuk:

  • async loading,
  • dialog lifecycle,
  • toast queue,
  • route transitions,
  • drag/drop,
  • interrupted animations,
  • exit before unmount.

Jangan memaksa CSS menyelesaikan state management kompleks sendirian.


26. View Transitions Overview

View Transitions API memungkinkan transisi visual antar state/halaman dengan snapshot yang dianimasikan. Ini menarik untuk route/page transition, tetapi harus dipakai selektif.

Prinsip:

  • cocok untuk menjaga orientasi antar view yang jelas berhubungan,
  • jangan dipakai untuk semua navigasi tanpa alasan,
  • pastikan reduced-motion fallback,
  • pastikan tidak mengganggu focus/navigation semantics,
  • cek browser support/Baseline sebelum production strategy.

Contoh CSS konseptual:

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: var(--motion-duration-slow);
}

@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 0ms;
  }
}

View transition adalah enhancement, bukan core usability requirement.


27. Enterprise Patterns

Save Feedback

.save-indicator {
  transition: color var(--motion-duration-fast) ease;
}

.save-indicator[data-state="saved"] {
  color: var(--color-status-success-text);
}

Jangan hanya flash hijau. Tampilkan teks seperti “Saved” atau “All changes saved”.

Row Update

@keyframes row-update {
  from { background: var(--color-status-info-bg); }
  to { background: transparent; }
}

.data-table tr[data-updated="true"] {
  animation: row-update 1200ms ease-out 1;
}

Destructive Confirmation

Destructive action tidak perlu animasi playful. Clarity lebih penting.

.destructive-dialog {
  border-color: var(--color-status-danger-border);
}

Motion boleh membantu entrance, tetapi jangan mengurangi seriousness.


28. Performance Debugging

Gunakan DevTools:

  • Performance panel untuk melihat long frames,
  • rendering tools untuk paint flashing/layer borders jika tersedia,
  • animation inspector untuk timeline/easing,
  • computed styles untuk memastikan property yang dianimasikan eksplisit,
  • FPS/performance monitor untuk jank.

Debugging flow:


29. Animation Failure Taxonomy

GejalaPenyebab umumSolusi
UI terasa lambatduration terlalu panjangturunkan duration, pakai direct state
Jank saat expandanimasi width/height/layoutgunakan transform/opacity atau no animation
Focus hilangmotion tidak sinkron dengan focus managementsinkronkan state accessibility
User mual/terganggumovement besar/parallax/zoomreduced motion + kurangi motion
Hidden element masih clickableopacity sajapakai hidden, display, inert, pointer/focus handling
Transition aneh setelah CSS berubahtransition: allproperty eksplisit
Infinite animation borosbanyak skeleton/spinnerbatasi jumlah, stop saat tidak perlu
Focus indicator terlambattransition pada outline/focusfocus harus immediate

30. Motion Accessibility Checklist

  • Apakah motion punya purpose jelas?
  • Apakah informasi tetap tersedia tanpa motion?
  • Apakah ada prefers-reduced-motion handling?
  • Apakah focus state langsung terlihat?
  • Apakah motion tidak membuat user kehilangan posisi?
  • Apakah elemen hidden benar-benar tidak bisa difokuskan/clicked?
  • Apakah animation tidak flashing?
  • Apakah loading animation berhenti saat selesai/error?
  • Apakah toast penting tidak hilang terlalu cepat?
  • Apakah keyboard dan screen reader flow tetap benar?

31. Motion Code Review Checklist

  • Hindari transition: all.
  • Animasi property eksplisit.
  • Prioritaskan transform dan opacity.
  • Jangan animasikan layout kecuali sudah diuji dan punya alasan.
  • Duration pendek untuk micro-interaction.
  • Gunakan motion tokens.
  • Reduced motion tersedia.
  • Tidak ada infinite animation tanpa kebutuhan.
  • will-change tidak dipakai sembarangan.
  • Dialog/popover motion sinkron dengan lifecycle/focus.
  • Motion tidak menjadi satu-satunya carrier makna.
  • Test di low-end device atau throttled environment.

32. Practice 1 — Button Interaction States

Buat button dengan:

  • hover background,
  • active tactile feedback,
  • focus visible immediate,
  • disabled state,
  • reduced-motion fallback.

Skeleton:

.button {
  transition:
    background-color var(--motion-duration-fast) ease,
    transform var(--motion-duration-fast) ease;
}

.button:hover {
  background: var(--color-bg-action-hover);
}

.button:active {
  transform: translateY(1px);
}

.button:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .button:active {
    transform: none;
  }
}

Evaluasi:

  • apakah focus terlihat tanpa delay?
  • apakah active feedback terlalu besar?
  • apakah disabled tetap readable?

33. Practice 2 — Popover Motion

Requirement:

  • muncul cepat,
  • tidak bergerak jauh,
  • reduced motion menghapus translate,
  • state hidden tidak bisa difokuskan.

HTML konseptual:

<button aria-expanded="false" aria-controls="filter-popover">Filters</button>
<div id="filter-popover" class="popover" hidden>
  <!-- filter controls -->
</div>

CSS:

.popover {
  opacity: 0;
  transform: translateY(-0.25rem);
  transition: opacity 120ms ease, transform 120ms ease;
}

.popover[data-open="true"] {
  opacity: 1;
  transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
  .popover {
    transform: none;
  }
}

Catatan: hidden perlu dikelola oleh JavaScript jika kamu ingin exit animation.


34. Practice 3 — Skeleton with Reduced Motion

Requirement:

  • skeleton tidak menyebabkan layout shift,
  • loop tidak terlalu cepat,
  • reduced motion menghentikan animation,
  • error state menggantikan loading jika gagal.

CSS:

.skeleton-line {
  inline-size: var(--skeleton-width, 100%);
  block-size: 1rem;
  border-radius: var(--radius-sm);
  background: var(--color-bg-muted);
  animation: skeleton-pulse 1.2s ease-in-out infinite;
}

@keyframes skeleton-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}

@media (prefers-reduced-motion: reduce) {
  .skeleton-line {
    animation: none;
  }
}

35. Practice 4 — Row Update Indicator

Buat row table yang baru diperbarui:

  • highlight selama 1.2 detik,
  • reduced motion mengganti highlight temporal dengan outline statis,
  • teks/status tetap menjelaskan perubahan.
@keyframes row-highlight {
  from { background-color: var(--color-status-info-bg); }
  to { background-color: transparent; }
}

tr[data-updated="true"] {
  animation: row-highlight 1.2s ease-out 1;
}

@media (prefers-reduced-motion: reduce) {
  tr[data-updated="true"] {
    animation: none;
    outline: 2px solid var(--color-status-info-border);
    outline-offset: -2px;
  }
}

36. Capstone Mini-Exercise

Tambahkan motion system ke case management UI dari part sebelumnya:

  • button states,
  • card hover untuk clickable case card,
  • filter popover enter,
  • dialog enter,
  • toast saved notification,
  • updated row highlight,
  • skeleton loading,
  • reduced-motion mode.

Batasan:

  • tidak boleh transition: all,
  • tidak boleh animasi layout besar,
  • semua duration/easing dari token,
  • motion tetap clear di keyboard navigation,
  • reduced motion menghapus movement besar,
  • tidak ada informasi yang hanya disampaikan lewat motion.

37. Key Takeaways

  • Motion adalah feedback system, bukan dekorasi.
  • Transition cocok untuk state A ke state B; animation cocok untuk sequence/keyframes.
  • Hindari transition: all.
  • transform dan opacity biasanya lebih aman daripada property layout.
  • Duration micro-interaction harus pendek.
  • Easing memberi rasa dan harus konsisten.
  • Motion tokens membuat animasi maintainable.
  • Reduced motion adalah requirement accessibility.
  • Opacity tidak sama dengan hidden.
  • Dialog/popover motion harus sinkron dengan focus dan lifecycle.
  • Infinite animation harus dibatasi dan dihentikan saat tidak perlu.
  • Debug animation dengan memahami rendering pipeline: layout, paint, composite.

38. References

  • CSS Transitions Module Level 1: https://www.w3.org/TR/css-transitions-1/
  • CSS Transitions Module Level 2: https://www.w3.org/TR/css-transitions-2/
  • CSS Animations Module Level 1: https://www.w3.org/TR/css-animations-1/
  • CSS Transforms Module Level 1: https://www.w3.org/TR/css-transforms-1/
  • CSS Transforms Module Level 2: https://www.w3.org/TR/css-transforms-2/
  • CSS View Transitions Module Level 1: https://www.w3.org/TR/css-view-transitions-1/
  • MDN Web Docs — CSS transitions: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_transitions
  • MDN Web Docs — CSS animations: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_animations
  • MDN Web Docs — transition: https://developer.mozilla.org/en-US/docs/Web/CSS/transition
  • MDN Web Docs — animation: https://developer.mozilla.org/en-US/docs/Web/CSS/animation
  • MDN Web Docs — transform: https://developer.mozilla.org/en-US/docs/Web/CSS/transform
  • MDN Web Docs — prefers-reduced-motion: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
  • WCAG 2.2 — Animation from Interactions: https://www.w3.org/WAI/WCAG22/Understanding/animation-from-interactions.html
  • WCAG 2.2 — Three Flashes or Below Threshold: https://www.w3.org/WAI/WCAG22/Understanding/three-flashes-or-below-threshold.html
Lesson Recap

You just completed lesson 24 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.