Quick implementation
@keyframes shake {
0%, 100% { transform: translateX(0); }
10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); }
20%, 40%, 60%, 80% { transform: translateX(4px); }
}
.shake-element {
animation: shake 0.5s ease-in-out;
}
@media (prefers-reduced-motion: reduce) {
.shake-element {
animation: none;
}
}
Prompt this to your LLM
Includes role, constraints, two framework variants, and edge cases to handle.
You are a senior frontend engineer specializing in accessible web animations.
Your goal: Implement a shake animation component that provides visual feedback for error states, form validation failures, or attention-seeking alerts.
Technical constraints:
1. Use pure CSS @keyframes animation (no JavaScript animation libraries)
2. Animation must complete in 0.4–0.6 seconds for snappy feedback
3. Shake distance should be subtle (4–6px) to avoid disorienting the user
4. Must respect prefers-reduced-motion media query for accessibility
5. Use CSS custom properties for timing and distance values
6. Support both horizontal and vertical shake variants with the same keyframe logic
Vanilla implementation:
- Define @keyframes with alternating left and right translateX values
- Apply animation class on demand via JavaScript classList.add()
- Remove class after animation completes using animationend event listener
React implementation:
- Create a custom hook useShake() that returns [isShaking, triggerShake]
- Use CSS Modules with @keyframes definition
- Apply conditional className when isShaking is true
- Use useEffect with onAnimationEnd callback to reset state
Edge cases to handle:
1. Multiple rapid shake triggers should queue or debounce
2. Component should not shake during page prefers-reduced-motion setting
3. Animation should auto-cleanup even if user navigates away
4. Nested elements with their own animations should not conflict
Why this matters in 2026
Shake animations have become a universal visual language for error feedback. From form validation to notification dismissals, the shake tells users "something went wrong" instantly—no text required. In an era where UX is competitive advantage, millisecond-perfect feedback separates good products from great ones.
CSS-based shake is superior to JavaScript animation libraries because it's performant, doesn't block the main thread, and respects system accessibility preferences automatically. A single keyframe definition works for any element, making it trivially reusable.
The logic
The shake animation uses translateX to move the element left and right in rapid alternation. Each keyframe step represents a moment in the shake sequence. The ease-in-out timing function ensures the motion feels natural, accelerating into each direction and decelerating at the extremes.
The animation completes in half a second—fast enough to feel responsive without lingering. Total travel distance is 8px (4px left, 4px right), which is noticeable but not jarring. The @media (prefers-reduced-motion: reduce) query ensures users with motion sensitivity or vestibular disorders see no animation at all, as required by WCAG 2.1.
Accessibility & performance
Accessibility: Always check the prefers-reduced-motion media query. Some users experience motion sickness or vertigo from animations, and respecting their OS preference is not optional—it's a legal requirement in many jurisdictions. For shake animations specifically, consider providing haptic feedback (vibration) on mobile as an alternative.
Performance: CSS animations on transform properties (like translateX) are GPU-accelerated and don't trigger layout recalculations. A shake animation has zero performance cost compared to JavaScript-driven animations. Use will-change: transform only if the element is shaking constantly; one-off shakes don't need it.