8.3 KiB
Micro-interaction Inspiration
Subtle animations that bring interfaces to life.
Button Interactions
Stripe
URL: https://stripe.com What to study:
- Button hover states
- Loading indicators
- Success animations
- Gradient button effects
Patterns:
/* Stripe-style button */
.btn {
background: linear-gradient(135deg, #667eea, #764ba2);
transition: transform 0.2s, box-shadow 0.2s;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
}
.btn:active {
transform: translateY(0);
}
Linear
URL: https://linear.app What to study:
- Subtle hover lifts
- Icon animations in buttons
- Loading spinners
- Toggle switches
Vercel
URL: https://vercel.com What to study:
- Deploy button states
- Copy code feedback
- Navigation highlights
- Toast notifications
Form Interactions
Typeform
URL: https://www.typeform.com What to study:
- Field focus states
- Input validation feedback
- Progress indication
- Multi-step transitions
Stripe Elements
URL: https://stripe.com/docs/payments/elements What to study:
- Card input formatting
- Real-time validation
- Error messaging
- Success feedback
Framer
URL: https://www.framer.com What to study:
- Placeholder animations
- Label transitions
- Dropdown menus
- Color pickers
Navigation Interactions
Apple
URL: https://www.apple.com What to study:
- Nav hover underlines
- Dropdown reveals
- Mega menu animations
- Mobile menu transitions
Stripe (Nav)
URL: https://stripe.com What to study:
- Products dropdown
- Hover timing
- Background transitions
- Mobile adaptation
Linear (Nav)
URL: https://linear.app What to study:
- Minimal nav hover
- Command palette (⌘K)
- Keyboard navigation
- Focus indicators
Feedback & States
Notion
URL: https://www.notion.so What to study:
- Drag and drop feedback
- Checkbox animations
- Page loading states
- Collaborative presence
Figma
URL: https://www.figma.com What to study:
- Cursor multiplayer
- Selection feedback
- Tool switching
- Zoom transitions
GitHub
URL: https://github.com What to study:
- Contribution graph hover
- Diff highlighting
- Copy feedback
- Loading skeletons
Key Patterns Observed
Hover States
Common patterns:
- Lift (translateY -2px to -4px)
- Scale (1.02 to 1.05)
- Shadow increase
- Background shift
- Border/outline appear
- Icon animation
Timing:
- Duration: 150-300ms
- Easing: ease-out or power2.out
Focus States
Accessibility-first:
- Visible outline
- Color contrast
- Motion for enhancement
Implementation:
.element:focus-visible {
outline: 2px solid var(--color-accent);
outline-offset: 2px;
}
Loading States
Types:
- Skeleton screens
- Spinner (use sparingly)
- Progress bar
- Shimmer effect
- Optimistic UI
Skeleton example:
.skeleton {
background: linear-gradient(
90deg,
var(--color-bg-secondary) 25%,
var(--color-bg-tertiary) 50%,
var(--color-bg-secondary) 75%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
Success/Error States
Success:
- Green accent
- Checkmark animation
- Brief celebration
- Auto-dismiss
Error:
- Red accent
- Shake animation (subtle)
- Clear messaging
- Recovery path
Implementation Reference
Hover Lift
.card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.1);
}
Button Loading
async function handleSubmit(btn) {
btn.classList.add('loading');
btn.disabled = true;
try {
await submitForm();
btn.classList.remove('loading');
btn.classList.add('success');
// Reset after delay
setTimeout(() => {
btn.classList.remove('success');
btn.disabled = false;
}, 2000);
} catch (error) {
btn.classList.remove('loading');
btn.classList.add('error');
// Handle error
}
}
.btn {
position: relative;
}
.btn.loading .btn-text {
opacity: 0;
}
.btn.loading::after {
content: '';
position: absolute;
width: 16px;
height: 16px;
border: 2px solid currentColor;
border-right-color: transparent;
border-radius: 50%;
animation: spin 0.6s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
Checkbox Animation
.checkbox-custom {
width: 20px;
height: 20px;
border: 2px solid var(--color-border);
border-radius: 4px;
position: relative;
transition: border-color 0.2s, background 0.2s;
}
.checkbox-custom::after {
content: '';
position: absolute;
left: 6px;
top: 2px;
width: 5px;
height: 10px;
border: 2px solid white;
border-top: none;
border-left: none;
transform: rotate(45deg) scale(0);
transition: transform 0.2s ease;
}
input:checked + .checkbox-custom {
background: var(--color-accent);
border-color: var(--color-accent);
}
input:checked + .checkbox-custom::after {
transform: rotate(45deg) scale(1);
}
Toast Notification
function showToast(message, type = 'info') {
const toast = document.createElement('div');
toast.className = `toast toast-${type}`;
toast.textContent = message;
document.body.appendChild(toast);
// Animate in
gsap.fromTo(toast,
{ opacity: 0, y: 20 },
{ opacity: 1, y: 0, duration: 0.3 }
);
// Auto dismiss
setTimeout(() => {
gsap.to(toast, {
opacity: 0,
y: -20,
duration: 0.3,
onComplete: () => toast.remove()
});
}, 3000);
}
Copy to Clipboard
async function copyToClipboard(text, button) {
await navigator.clipboard.writeText(text);
const originalText = button.textContent;
button.textContent = 'Copied!';
button.classList.add('copied');
setTimeout(() => {
button.textContent = originalText;
button.classList.remove('copied');
}, 2000);
}
Timing Guidelines
By Interaction Type
| Interaction | Duration | Easing |
|---|---|---|
| Hover | 150-200ms | ease-out |
| Click feedback | 100ms | ease-out |
| Page transition | 300-500ms | ease-in-out |
| Loading appear | 200ms | ease-out |
| Toast enter | 300ms | ease-out |
| Toast exit | 200ms | ease-in |
Rule of Thumb
Faster = More responsive (hovers, clicks)
Slower = More dramatic (page changes, reveals)
Never exceed 500ms for UI feedback
Questions to Ask
When studying these sites:
- What triggers the animation?
- What's the duration and easing?
- Does it provide clear feedback?
- Does it work without motion?
- Is it consistent across the site?
- Does it feel purposeful or decorative?
Production Micro-Interaction Patterns
Real-world micro-interactions from a modern digital studio site, showing the timing and easing values that create premium feel.
Rolling Text Nav Hover
Dual-layer text where the bottom label slides up as the top slides away. Pure CSS, no JavaScript. Uses cubic-bezier(0.22, 1, 0.36, 1) at 0.35s for a snappy-but-smooth feel.
Condensing Navbar on Scroll
Nav pill shrinks from 5rem to 3.25rem height with backdrop blur appearing. Transitions use cubic-bezier(0.22, 1, 0.36, 1) at 0.8s — intentionally slow for a premium, unhurried feel.
Grid-Template-Rows Accordion
FAQ accordion using grid-template-rows: 0fr → 1fr for smooth height animation without JavaScript height calculation. Plus icon rotates 45° to become an X. Both at 300ms with cubic-bezier(0.22, 1, 0.36, 1).
Icon Rotation on Hover
Star icon on button rotates 90° on hover. 0.35s with cubic-bezier(0.4, 0, 0.2, 1). Subtle enough to notice, fast enough to feel responsive.
Form Input Underline Focus
Border-bottom transitions from muted to accent color on focus. 0.3s, simple ease. Clean feedback that the field is active.
Key Timing Principles
- 0.2-0.35s: Interactive elements (buttons, links, icons) — fast, responsive
- 0.3s: State changes (focus, active, selected) — noticeable but not sluggish
- 0.5-0.8s: Layout transitions (navbar, accordion) — deliberate, premium
- Two easings cover everything:
cubic-bezier(0.22, 1, 0.36, 1)for layout,cubic-bezier(0.4, 0, 0.2, 1)for interaction
→ See elite-css-animations/visual-effects.md for complete CSS implementations.