Animation Guidelines
หลักการ
Animation ต้อง subtle, purposeful ไม่ใช่ decoration เกินจำเป็น — สอดคล้องกับ vibe minimal/premium/boardroom-ready ของแบรนด์ การเคลื่อนไหวมีไว้เพื่อ สื่อความสัมพันธ์และทิศทาง (อะไรมาจากไหน ไปไหน) ไม่ใช่เพื่อโชว์ ห้ามใช้เอฟเฟกต์ bounce/overshoot/หวือหวา
Duration Tokens
ค่าที่แนะนำสำหรับทุก transition/animation — สั้นเข้าไว้ ยาวสุดของ UI ปกติไม่ควรเกิน 300ms:
| Token | ค่า | ใช้กับ |
|---|---|---|
motion.duration.instant | 100ms | micro-interaction (checkbox, toggle) |
motion.duration.fast | 150ms | hover, color/opacity transition |
motion.duration.base | 200ms | transition UI ทั่วไป (default) |
motion.duration.slow | 300ms | card/modal เข้า, dropdown |
motion.duration.slower | 500ms | page transition, overlay เต็มจอ |
ลูกบอลเคลื่อนที่ไป-กลับตาม duration ที่เลือก · กดเปลี่ยนความเร็วเพื่อสัมผัสความต่าง
Easing Curves
| Token | cubic-bezier | ใช้กับ |
|---|---|---|
motion.ease.standard | (0.4, 0, 0.2, 1) | transition ทั่วไป (เข้า-ออกพร้อมกัน) |
motion.ease.decelerate | (0, 0, 0.2, 1) | element ที่ เข้า (เข้าเร็ว ชะลอลงตอนจบ) |
motion.ease.accelerate | (0.4, 0, 1, 1) | element ที่ ออก (เร่งออกไป) |
linear | — | เฉพาะ spinner/progress ที่หมุนต่อเนื่อง |
ชี้เมาส์ที่แถบสีเทา — ลูกบอลจะเคลื่อนที่ด้วย easing curve ที่ต่างกัน สังเกตความเร็วต้น-ปลายของแต่ละ curve
Enter / Exit Patterns
- Enter: fade-in + เลื่อนเบาๆ 8–16px หรือ scale จาก 0.98 → 1 ใช้
decelerate— ห้ามเลื่อนระยะไกลหรือ slide เต็มจอ - Exit: fade-out เร็วกว่า enter หนึ่งสเต็ป ใช้
accelerate(ของที่กำลังจากไปไม่ต้องดึงความสนใจ) - ระยะการเคลื่อนต้องเล็ก — premium คือ "รู้สึกได้แต่ไม่ตะโกน"
Loading States
- Skeleton shimmer เป็นค่าเริ่มต้น (ดู States & Feedback) — shimmer วนช้าๆ ~1.4s
- Spinner ใช้
linearหมุนต่อเนื่อง สีเส้น#FF6727 - Progress bar เคลื่อนแบบ
linearสะท้อนความคืบหน้าจริง อย่าปลอม
Hover / Active Transitions
- Hover: เปลี่ยน background/สี/เงาใน
fast(150ms)standard— ปุ่มยกตัวด้วยshadow.md(ดู Spacing, Radius & Elevation) - Active/pressed: scale 0.98 สั้นๆ ให้ feedback การกด แล้วคืนสภาพ
- โทเคนสี hover ใช้
color.primary-hover(#C43400) ตามที่กำหนดใน component token — ดู Buttons & Cards
Page Transitions
- ใช้ fade อ่อนๆ
base–slower(200–500ms) ตอนเปลี่ยนหน้า/route ห้ามใช้ slide/flip/zoom หวือหวา - คงตำแหน่งองค์ประกอบร่วม (โลโก้/นาว) ให้นิ่ง ไม่กระตุกระหว่างเปลี่ยนหน้า
Reduced Motion (บังคับ)
เคารพ prefers-reduced-motion เสมอ — ผู้ใช้ที่ตั้งค่านี้ (เวียนหัวจากการเคลื่อนไหว) ต้องได้ประสบการณ์ที่นิ่ง โดยเนื้อยังครบ:
ปุ่มด้านบนจำลอง prefers-reduced-motion: reduce — กดเพื่อดูว่า animation ทั้งหมดหยุดอย่างไร
ตัวเว็บจริงจะอ่านค่าจาก OS โดยอัตโนมัติ
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
* {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
JS-driven animation (เช่น Chart.js) ต้องเช็ค matchMedia('(prefers-reduced-motion: reduce)') เองด้วย (ดู Chart.js Theme)
Do / Don't
| ✅ Do | ❌ Don't |
|---|---|
| duration ≤ 300ms สำหรับ UI ทั่วไป | animation ยืดยาด > 500ms ใน interaction |
| เลื่อน 8–16px + fade ตอน enter | slide/zoom เต็มจอหวือหวา |
| exit เร็วกว่า enter | เอฟเฟกต์ bounce/overshoot |
| เคารพ reduced-motion ทั้ง CSS และ JS | บังคับ animation ทุกกรณี |
| ใช้ animation เพื่อสื่อทิศทาง/ความสัมพันธ์ | animation เพื่อตกแต่งอย่างเดียว |