$npx -y skills add dylantarre/design-system-skills --skill animation-principlesApplies Disney's 12 animation principles to UI motion design. Use when improving animation quality, designing micro-interactions, creating easing curves, or making transitions feel natural and purposeful.
| 1 | # Animation Principles for UI |
| 2 | |
| 3 | ## Overview |
| 4 | |
| 5 | Apply Disney's 12 principles of animation to create UI motion that feels natural, purposeful, and delightful. These principles, developed in the 1930s for character animation, translate directly to modern interface design. |
| 6 | |
| 7 | ## When to Use |
| 8 | |
| 9 | - Designing micro-interactions and transitions |
| 10 | - Making animations feel more natural and polished |
| 11 | - Reviewing animation quality in a design system |
| 12 | - Training team members on motion design fundamentals |
| 13 | - Creating animation guidelines for a design system |
| 14 | |
| 15 | ## Quick Reference: The 12 Principles |
| 16 | |
| 17 | | Principle | UI Application | Priority | |
| 18 | |-----------|----------------|----------| |
| 19 | | Easing (Slow in/out) | All transitions | Essential | |
| 20 | | Anticipation | Button press, drag start | High | |
| 21 | | Follow-through | Modals, dropdowns, toasts | High | |
| 22 | | Secondary Action | Loading states, notifications | Medium | |
| 23 | | Timing | Duration based on distance/importance | Essential | |
| 24 | | Squash & Stretch | Buttons, toggles, playful UI | Medium | |
| 25 | | Staging | Focus attention, reduce distraction | High | |
| 26 | | Arc | Natural movement paths | Medium | |
| 27 | | Exaggeration | Emphasis, delight moments | Low | |
| 28 | | Solid Drawing | Consistent 3D perspective | Low | |
| 29 | | Appeal | Brand personality | Medium | |
| 30 | | Straight Ahead / Pose to Pose | Complex sequences | Low | |
| 31 | |
| 32 | --- |
| 33 | |
| 34 | ## 1. Easing (Slow In and Slow Out) |
| 35 | |
| 36 | **Principle:** Objects don't start or stop instantly - they accelerate and decelerate. |
| 37 | |
| 38 | **In UI:** Never use `linear` timing for UI animations. Use easing curves. |
| 39 | |
| 40 | ### CSS Implementation |
| 41 | |
| 42 | ```css |
| 43 | :root { |
| 44 | /* Standard easing - use for most transitions */ |
| 45 | --ease-out: cubic-bezier(0.0, 0.0, 0.2, 1); /* Decelerate */ |
| 46 | --ease-in: cubic-bezier(0.4, 0.0, 1, 1); /* Accelerate */ |
| 47 | --ease-in-out: cubic-bezier(0.4, 0.0, 0.2, 1); /* Both */ |
| 48 | |
| 49 | /* Expressive easing - more personality */ |
| 50 | --ease-expressive: cubic-bezier(0.4, 0.14, 0.3, 1); |
| 51 | |
| 52 | /* Spring-like - for playful UI */ |
| 53 | --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); |
| 54 | --ease-overshoot: cubic-bezier(0.175, 0.885, 0.32, 1.275); |
| 55 | } |
| 56 | |
| 57 | /* ❌ Bad - robotic, unnatural */ |
| 58 | .modal { |
| 59 | transition: opacity 200ms linear; |
| 60 | } |
| 61 | |
| 62 | /* ✅ Good - natural deceleration */ |
| 63 | .modal { |
| 64 | transition: opacity 200ms var(--ease-out); |
| 65 | } |
| 66 | ``` |
| 67 | |
| 68 | ### When to Use Each |
| 69 | |
| 70 | | Easing | Use Case | |
| 71 | |--------|----------| |
| 72 | | ease-out | Elements entering (modals, dropdowns, toasts) | |
| 73 | | ease-in | Elements exiting, leaving viewport | |
| 74 | | ease-in-out | Elements that stay on screen (position changes, morphing) | |
| 75 | | bounce/overshoot | Playful interactions, success states, toggle switches | |
| 76 | |
| 77 | --- |
| 78 | |
| 79 | ## 2. Anticipation |
| 80 | |
| 81 | **Principle:** Prepare the audience for an action before it happens. |
| 82 | |
| 83 | **In UI:** Give users a hint that something is about to happen. |
| 84 | |
| 85 | ### Examples |
| 86 | |
| 87 | ```css |
| 88 | /* Button press - slight scale down before action */ |
| 89 | .button:active { |
| 90 | transform: scale(0.97); |
| 91 | transition: transform 50ms var(--ease-in); |
| 92 | } |
| 93 | |
| 94 | .button:not(:active) { |
| 95 | transition: transform 150ms var(--ease-out); |
| 96 | } |
| 97 | |
| 98 | /* Drag anticipation - lift before moving */ |
| 99 | .draggable.is-lifting { |
| 100 | transform: scale(1.02); |
| 101 | box-shadow: var(--shadow-lg); |
| 102 | transition: all 100ms var(--ease-out); |
| 103 | } |
| 104 | |
| 105 | /* Pull-to-refresh - resistance before release */ |
| 106 | .pull-indicator { |
| 107 | transform: translateY(calc(var(--pull-distance) * 0.4)); |
| 108 | /* Rubber band effect - moves slower than finger */ |
| 109 | } |
| 110 | ``` |
| 111 | |
| 112 | ### Swipe Action Anticipation |
| 113 | |
| 114 | ```css |
| 115 | /* Card swipe - tilt in direction of swipe */ |
| 116 | .card.swiping-right { |
| 117 | transform: translateX(var(--swipe-x)) rotate(calc(var(--swipe-x) * 0.05deg)); |
| 118 | } |
| 119 | ``` |
| 120 | |
| 121 | --- |
| 122 | |
| 123 | ## 3. Follow-Through and Overlapping Action |
| 124 | |
| 125 | **Principle:** Different parts of an object move at different rates; motion continues after the main action stops. |
| 126 | |
| 127 | **In UI:** Elements don't stop all at once. Parts settle at different times. |
| 128 | |
| 129 | ### Modal with Follow-Through |
| 130 | |
| 131 | ```css |
| 132 | /* Backdrop and content animate separately */ |
| 133 | .modal-backdrop { |
| 134 | animation: fadeIn 200ms var(--ease-out); |
| 135 | } |
| 136 | |
| 137 | .modal-content { |
| 138 | animation: slideUp 300ms var(--ease-out); |
| 139 | animation-delay: 50ms; /* Slightly after backdrop */ |
| 140 | } |
| 141 | |
| 142 | @keyframes slideUp { |
| 143 | from { |
| 144 | opacity: 0; |
| 145 | transform: translateY(20px) scale(0.98); |
| 146 | } |
| 147 | to { |
| 148 | opacity: 1; |
| 149 | transform: translateY(0) scale(1); |
| 150 | } |
| 151 | } |
| 152 | ``` |
| 153 | |
| 154 | ### Staggered List Items |
| 155 | |
| 156 | ```css |
| 157 | /* Items enter one after another */ |
| 158 | .list-item { |
| 159 | animation: fadeSlideIn 300ms var(--ease-out) both; |
| 160 | } |
| 161 | |
| 162 | .list-item:nth-child(1) { animation-delay: 0ms; } |
| 163 | .list-item:nth-child(2) { animation-delay: 50ms; } |
| 164 | .list-item:nth-child(3) { animation-delay: 100ms; } |
| 165 | .list-item:nth-child(4) { animation-delay: 150ms; } |
| 166 | |
| 167 | /* Or dynamically with CSS custom properties */ |
| 168 | .list-item { |
| 169 | animation-delay: calc(var(--index) * 50ms); |
| 170 | } |
| 171 | ``` |
| 172 | |
| 173 | ### React Implementation |
| 174 | |
| 175 | ```tsx |
| 176 | // Staggered children |
| 177 | function StaggeredList({ children }) { |