Reduced Motion ๐ฌ
Creating accessible animations that respect user preferences and prevent motion sickness. Essential for users with vestibular disorders, motion sensitivity, and cognitive disabilities.
What is Reduced Motion?
Reduced Motion is an accessibility feature that allows users to indicate their preference for minimal animation and motion on websites. This is crucial for users who experience motion sickness, vestibular disorders, or find animations distracting.
๐คข Motion Sensitivity
Prevents dizziness and nausea for users with vestibular disorders
๐ง Cognitive Support
Reduces distractions for users with attention and cognitive disabilities
โก Performance
Improves performance and battery life on mobile devices
Reduced Motion Fundamentals
Key Principles:
- Respect user preferences through CSS media queries and JavaScript detection
- Provide meaningful alternatives to essential animations
- Test thoroughly with reduced motion enabled on different devices
- Consider progressive enhancement - start with no motion
- Document your approach for team consistency and maintenance
Reduced Motion Fundamentals Implementation
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Reduced Motion - Accessible Animation & Motion Design</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', sans-serif; line-height: 1.6; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; padding: 2rem; color: #2c3e50; } .container { max-width: 1200px; margin: 0 auto; } .header { text-align: center; margin-bottom: 3rem; color: white; } .header h1 { font-size: 3rem; margin-bottom: 1rem; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); } .principles-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(500px, 1fr)); gap: 2rem; margin-bottom: 3rem; } .principle-card { background: white; border-radius: 15px; padding: 2rem; box-shadow: 0 10px 30px rgba(0,0,0,0.1); } .motion-demo { display: grid; grid-template-columns: 1fr 1fr; gap: 2rem; margin: 2rem 0; padding: 2rem; background: #f8f9fa; border-radius: 10px; } .demo-box { padding: 3rem; border-radius: 8px; text-align: center; font-weight: bold; color: white; position: relative; overflow: hidden; } .animated-box { background: #e74c3c; animation: bounce 2s infinite; } .reduced-box { background: #2ecc71; } @keyframes bounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-20px); } } .interactive-demo { background: white; padding: 2rem; border-radius: 10px; margin: 2rem 0; box-shadow: 0 4px 6px rgba(0,0,0,0.1); } .button-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin: 2rem 0; } .btn { padding: 1rem 2rem; border: none; border-radius: 8px; font-weight: 600; cursor: pointer; transition: all 0.3s ease; text-align: center; font-size: 1rem; } .btn-animated { background: #3498db; color: white; animation: pulse 2s infinite; } .btn-reduced { background: #9b59b6; color: white; } @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } } .user-scenarios { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1rem; margin: 2rem 0; } .scenario-card { background: #e8f4fd; padding: 1.5rem; border-radius: 8px; border-left: 4px solid #3498db; } .code-example { background: #2c3e50; color: #ecf0f1; padding: 1.5rem; border-radius: 8px; font-family: 'Fira Code', monospace; font-size: 0.9rem; margin: 1rem 0; overflow-x: auto; } @media (prefers-reduced-motion: reduce) { .animated-box { animation: none; transform: translateY(0); } .btn-animated { animation: none; transform: scale(1); } * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } } @media (max-width: 768px) { .principles-grid { grid-template-columns: 1fr; } .motion-demo { grid-template-columns: 1fr; } .header h1 { font-size: 2rem; } } </style> </head> <body> <div class="container"> <div class="header"> <h1>๐ฌ Reduced Motion</h1> <p>Creating accessible animations that respect user preferences and prevent motion sickness</p> </div> <!-- Why Reduced Motion Matters --> <div class="principles-grid"> <div class="principle-card"> <h3>๐คข Why Reduced Motion Matters</h3> <p>Motion sensitivity affects millions of users worldwide and can cause serious discomfort.</p> <div class="user-scenarios"> <div class="scenario-card"> <h4>Vestibular Disorders</h4> <p>Users with inner ear conditions that cause dizziness and nausea from motion</p> </div> <div class="scenario-card"> <h4>Motion Sickness</h4> <p>General sensitivity to animated content and parallax effects</p> </div> <div class="scenario-card"> <h4>Cognitive Disabilities</h4> <p>Users who find excessive animation distracting or overwhelming</p> </div> <div class="scenario-card"> <h4>Attention Disorders</h4> <p>Animations can disrupt focus and concentration for some users</p> </div> </div> <div style="margin-top: 2rem;"> <h4>Impact Statistics:</h4> <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 1rem;"> <div style="background: #e8f4fd; padding: 1rem; border-radius: 8px; text-align: center;"> <div style="font-size: 1.5rem; font-weight: bold; color: #3498db;">35%</div> <div style="font-size: 0.9rem;">Adults over 40 experience vestibular dysfunction</div> </div> <div style="background: #e8f4fd; padding: 1rem; border-radius: 8px; text-align: center;"> <div style="font-size: 1.5rem; font-weight: bold; color: #3498db;">15-25%</div> <div style="font-size: 0.9rem;">People are highly sensitive to motion sickness</div> </div> </div> </div> </div> <!-- Motion Demo --> <div class="principle-card"> <h3>๐ฏ Motion Preference Demo</h3> <p>See how animations adapt based on user preferences.</p> <div class="motion-demo"> <div> <h4>Normal Motion</h4> <div class="demo-box animated-box"> Animated Box </div> <p style="margin-top: 1rem; font-size: 0.9rem; color: #666;"> This box bounces continuously with full animation </p> </div> <div> <h4>Reduced Motion</h4> <div class="demo-box reduced-box"> Static Box </div> <p style="margin-top: 1rem; font-size: 0.9rem; color: #666;"> This box remains static when reduced motion is preferred </p> </div> </div> <div class="interactive-demo"> <h4>Try enabling reduced motion in your system:</h4> <ul style="margin: 1rem 0; padding-left: 1.5rem;"> <li><strong>Windows:</strong> Settings โ Ease of Access โ Display โ Show animations</li> <li><strong>macOS:</strong> System Preferences โ Accessibility โ Display โ Reduce motion</li> <li><strong>iOS:</strong> Settings โ Accessibility โ Motion โ Reduce Motion</li> <li><strong>Android:</strong> Settings โ Accessibility โ Remove animations</li> </ul> </div> </div> </div> <!-- CSS Implementation --> <div class="principle-card"> <h3>๐จ CSS Reduced Motion Implementation</h3> <p>Using CSS media queries to respect user motion preferences.</p> <div class="code-example"> <span style="color: #7f8c8d;">/* Default animation styles */</span><br> <span style="color: #9b59b6;">.animated-element</span> {<br> <span style="color: #3498db;">animation</span>: <span style="color: #2ecc71;">bounce 2s infinite</span>;<br> <span style="color: #3498db;">transition</span>: <span style="color: #2ecc71;">transform 0.3s ease</span>;<br> }<br><br> <span style="color: #7f8c8d;">/* Reduced motion override */</span><br> @<span style="color: #9b59b6;">media</span> (<span style="color: #3498db;">prefers-reduced-motion</span>: <span style="color: #2ecc71;">reduce</span>) {<br> <span style="color: #9b59b6;">.animated-element</span> {<br> <span style="color: #3498db;">animation</span>: <span style="color: #2ecc71;">none</span>;<br> <span style="color: #3498db;">transition-duration</span>: <span style="color: #2ecc71;">0.01ms</span>;<br> }<br> } </div> <div class="button-grid"> <button class="btn btn-animated"> Animated Button </button> <button class="btn btn-reduced"> Static Button </button> </div> </div> <!-- JavaScript Implementation --> <div class="principle-card"> <h3>โก JavaScript Motion Detection</h3> <p>Detecting motion preferences in JavaScript for complex animations.</p> <div class="code-example"> <span style="color: #7f8c8d;">// Check if user prefers reduced motion</span><br> <span style="color: #9b59b6;">const</span> prefersReducedMotion = <span style="color: #3498db;">window</span>.<span style="color: #3498db;">matchMedia</span>(<span style="color: #2ecc71;">'(prefers-reduced-motion: reduce)'</span>).<span style="color: #3498db;">matches</span>;<br><br> <span style="color: #7f8c8d;">// Use in your animation logic</span><br> <span style="color: #9b59b6;">function</span> <span style="color: #3498db;">startAnimation</span>() {<br> <span style="color: #9b59b6;">if</span> (prefersReducedMotion) {<br> <span style="color: #9b59b6;">return</span>; <span style="color: #7f8c8d;">// Skip animation</span><br> }<br> <span style="color: #7f8c8d;">// Proceed with normal animation</span><br> <span style="color: #3498db;">animateElement</span>();<br> }<br><br> <span style="color: #7f8c8d;">// Listen for changes in preference</span><br> <span style="color: #3498db;">window</span>.<span style="color: #3498db;">matchMedia</span>(<span style="color: #2ecc71;">'(prefers-reduced-motion: reduce)'</span>).<span style="color: #3498db;">addEventListener</span>(<span style="color: #2ecc71;">'change'</span>, (e) => {<br> <span style="color: #9b59b6;">if</span> (e.matches) {<br> <span style="color: #7f8c8d;">// User enabled reduced motion</span><br> <span style="color: #3498db;">stopAllAnimations</span>();<br> } <span style="color: #9b59b6;">else</span> {<br> <span style="color: #7f8c8d;">// User disabled reduced motion</span><br> <span style="color: #3498db;">restoreAnimations</span>();<br> }<br> }); </div> </div> </div> </body> </html>
Animation Patterns
โณ Loading States
Replace spinning animations with static indicators or progress messages. Ensure users can still understand the loading state without motion.
๐ Interactions
Modify hover effects, card animations, and micro-interactions to use instant state changes instead of smooth transitions.
Animation Patterns Implementation
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Animation Patterns - Accessible Motion Design Patterns</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', sans-serif; line-height: 1.6; background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); min-height: 100vh; padding: 2rem; color: #2c3e50; } .container { max-width: 1200px; margin: 0 auto; } .header { text-align: center; margin-bottom: 3rem; color: white; } .header h1 { font-size: 3rem; margin-bottom: 1rem; text-shadow: 2px 2px 4px rgba(0,0,0,0.3); } .patterns-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(500px, 1fr)); gap: 2rem; margin-bottom: 3rem; } .pattern-card { background: white; border-radius: 15px; padding: 2rem; box-shadow: 0 10px 30px rgba(0,0,0,0.1); } .component-demo { background: #f8f9fa; padding: 2rem; border-radius: 10px; margin: 2rem 0; } .loading-demo { display: flex; justify-content: center; align-items: center; gap: 2rem; margin: 2rem 0; } .loader { width: 50px; height: 50px; border: 5px solid #f3f3f3; border-top: 5px solid #3498db; border-radius: 50%; } .loader-animated { animation: spin 2s linear infinite; } .loader-static { border-color: #2ecc71; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.5rem; margin: 2rem 0; } .product-card { background: white; padding: 1.5rem; border-radius: 12px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); transition: all 0.3s ease; } .product-card:hover { transform: translateY(-5px); box-shadow: 0 8px 25px rgba(0,0,0,0.15); } .notification-demo { padding: 1.5rem; margin: 1rem 0; border-radius: 8px; border-left: 4px solid; animation: slideIn 0.5s ease-out; } .notification-success { background: #d4edda; border-color: #28a745; color: #155724; } .notification-error { background: #f8d7da; border-color: #dc3545; color: #721c24; } @keyframes slideIn { from { transform: translateX(-100%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } .progress-demo { background: #f8f9fa; padding: 1rem; border-radius: 8px; margin: 1rem 0; } .progress-bar { height: 20px; background: #e9ecef; border-radius: 10px; overflow: hidden; margin: 0.5rem 0; } .progress-fill { height: 100%; background: #3498db; animation: progress 2s ease-in-out infinite; } .progress-fill-static { background: #2ecc71; width: 60%; } @keyframes progress { 0% { width: 0%; } 50% { width: 60%; } 100% { width: 0%; } } .code-example { background: #2c3e50; color: #ecf0f1; padding: 1.5rem; border-radius: 8px; font-family: 'Fira Code', monospace; font-size: 0.9rem; margin: 1rem 0; overflow-x: auto; } @media (prefers-reduced-motion: reduce) { .loader-animated { animation: none; border-color: #2ecc71; } .product-card:hover { transform: none; } .notification-demo { animation: none; } .progress-fill { animation: none; width: 60%; background: #2ecc71; } * { scroll-behavior: auto !important; } } @media (max-width: 768px) { .patterns-grid { grid-template-columns: 1fr; } .header h1 { font-size: 2rem; } } </style> </head> <body> <div class="container"> <div class="header"> <h1>๐ญ Animation Patterns</h1> <p>Common animation patterns with reduced motion alternatives</p> </div> <!-- Loading Animations --> <div class="patterns-grid"> <div class="pattern-card"> <h3>โณ Loading Animations</h3> <p>Provide static alternatives to spinning loaders and animated indicators.</p> <div class="component-demo"> <div class="loading-demo"> <div> <h4>Animated Loader</h4> <div class="loader loader-animated"></div> </div> <div> <h4>Static Indicator</h4> <div class="loader loader-static"></div> <div style="text-align: center; margin-top: 0.5rem; font-size: 0.8rem;">Loading...</div> </div> </div> </div> <div class="code-example"> <span style="color: #7f8c8d;">/* Loading animation with reduced motion support */</span><br> <span style="color: #9b59b6;">.loader</span> {<br> <span style="color: #3498db;">width</span>: <span style="color: #2ecc71;">50px</span>;<br> <span style="color: #3498db;">height</span>: <span style="color: #2ecc71;">50px</span>;<br> <span style="color: #3498db;">border</span>: <span style="color: #2ecc71;">5px solid #f3f3f3</span>;<br> <span style="color: #3498db;">border-top</span>: <span style="color: #2ecc71;">5px solid #3498db</span>;<br> <span style="color: #3498db;">border-radius</span>: <span style="color: #2ecc71;">50%</span>;<br> <span style="color: #3498db;">animation</span>: <span style="color: #2ecc71;">spin 2s linear infinite</span>;<br> }<br><br> @<span style="color: #9b59b6;">media</span> (<span style="color: #3498db;">prefers-reduced-motion</span>: <span style="color: #2ecc71;">reduce</span>) {<br> <span style="color: #9b59b6;">.loader</span> {<br> <span style="color: #3498db;">animation</span>: <span style="color: #2ecc71;">none</span>;<br> <span style="color: #3498db;">border-color</span>: <span style="color: #2ecc71;">#2ecc71</span>;<br> }<br> } </div> </div> <!-- Card Interactions --> <div class="pattern-card"> <h3>๐ Card Interactions</h3> <p>Hover effects and transitions that respect motion preferences.</p> <div class="card-grid"> <div class="product-card"> <h4>Product One</h4> <p style="color: #666; margin: 0.5rem 0;">Animated hover effect</p> <div style="font-size: 1.25rem; font-weight: bold; color: #3498db;">$99</div> </div> <div class="product-card"> <h4>Product Two</h4> <p style="color: #666; margin: 0.5rem 0;">Animated hover effect</p> <div style="font-size: 1.25rem; font-weight: bold; color: #3498db;">$149</div> </div> </div> <div class="code-example"> <span style="color: #7f8c8d;">/* Card hover effects */</span><br> <span style="color: #9b59b6;">.product-card</span> {<br> <span style="color: #3498db;">transition</span>: <span style="color: #2ecc71;">all 0.3s ease</span>;<br> }<br> <span style="color: #9b59b6;">.product-card</span>:hover {<br> <span style="color: #3498db;">transform</span>: <span style="color: #2ecc71;">translateY(-5px)</span>;<br> <span style="color: #3498db;">box-shadow</span>: <span style="color: #2ecc71;">0 8px 25px rgba(0,0,0,0.15)</span>;<br> }<br><br> @<span style="color: #9b59b6;">media</span> (<span style="color: #3498db;">prefers-reduced-motion</span>: <span style="color: #2ecc71;">reduce</span>) {<br> <span style="color: #9b59b6;">.product-card</span>:hover {<br> <span style="color: #3498db;">transform</span>: <span style="color: #2ecc71;">none</span>;<br> }<br> } </div> </div> </div> <!-- Notifications & Alerts --> <div class="pattern-card"> <h3>๐ Notifications & Alerts</h3> <p>Slide-in notifications with instant appearance for reduced motion.</p> <div class="component-demo"> <div class="notification-demo notification-success"> <strong>Success!</strong> Your action was completed successfully. </div> <div class="notification-demo notification-error"> <strong>Error!</strong> Something went wrong. Please try again. </div> </div> <div class="code-example"> <span style="color: #7f8c8d;">/* Notification animations */</span><br> <span style="color: #9b59b6;">.notification</span> {<br> <span style="color: #3498db;">animation</span>: <span style="color: #2ecc71;">slideIn 0.5s ease-out</span>;<br> }<br><br> @<span style="color: #9b59b6;">media</span> (<span style="color: #3498db;">prefers-reduced-motion</span>: <span style="color: #2ecc71;">reduce</span>) {<br> <span style="color: #9b59b6;">.notification</span> {<br> <span style="color: #3498db;">animation</span>: <span style="color: #2ecc71;">none</span>;<br> }<br> } </div> </div> <!-- Progress Indicators --> <div class="pattern-card"> <h3>๐ Progress Indicators</h3> <p>Animated progress bars with static alternatives.</p> <div class="progress-demo"> <h4>Animated Progress</h4> <div class="progress-bar"> <div class="progress-fill"></div> </div> <h4>Static Progress</h4> <div class="progress-bar"> <div class="progress-fill-static"></div> </div> </div> <div class="code-example"> <span style="color: #7f8c8d;">/* Progress bar animations */</span><br> <span style="color: #9b59b6;">.progress-fill</span> {<br> <span style="color: #3498db;">animation</span>: <span style="color: #2ecc71;">progress 2s ease-in-out infinite</span>;<br> }<br><br> @<span style="color: #9b59b6;">media</span> (<span style="color: #3498db;">prefers-reduced-motion</span>: <span style="color: #2ecc71;">reduce</span>) {<br> <span style="color: #9b59b6;">.progress-fill</span> {<br> <span style="color: #3498db;">animation</span>: <span style="color: #2ecc71;">none</span>;<br> <span style="color: #3498db;">width</span>: <span style="color: #2ecc71;">60%</span>;<br> <span style="color: #3498db;">background</span>: <span style="color: #2ecc71;">#2ecc71</span>;<br> }<br> } </div> </div> </div> </body> </html>
Testing & Implementation
๐ Browser Testing
Use browser DevTools to emulate reduced motion preferences without changing system settings
๐งช Manual Testing
Enable reduced motion in your operating system and test all animations and interactions
๐ค Automated Testing
Integrate reduced motion testing into your CI/CD pipeline with accessibility testing tools
Testing & Implementation Guide
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Testing & Implementation - Reduced Motion Best Practices</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: 'Inter', sans-serif; line-height: 1.6; background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 100%); min-height: 100vh; padding: 2rem; color: #2c3e50; } .container { max-width: 1200px; margin: 0 auto; } .header { text-align: center; margin-bottom: 3rem; } .header h1 { font-size: 3rem; margin-bottom: 1rem; color: #2c3e50; } .testing-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(350px, 1fr)); gap: 2rem; margin-bottom: 3rem; } .testing-card { background: white; border-radius: 15px; padding: 2rem; box-shadow: 0 10px 30px rgba(0,0,0,0.1); } .checklist { background: #f8f9fa; padding: 2rem; border-radius: 10px; margin: 1rem 0; } .checklist-item { display: flex; align-items: center; gap: 1rem; margin: 0.5rem 0; padding: 0.5rem; } .tool-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1.5rem; margin: 2rem 0; } .tool-card { background: #e8f4fd; padding: 1.5rem; border-radius: 10px; text-align: center; border-left: 4px solid #3498db; } .browser-demo { background: #2c3e50; color: #ecf0f1; padding: 1.5rem; border-radius: 8px; font-family: 'Fira Code', monospace; margin: 1rem 0; } .testing-demo { background: #fff3cd; border-left: 4px solid #ffc107; padding: 1.5rem; margin: 1rem 0; border-radius: 5px; } .best-practices { background: #d4edda; border-left: 4px solid #28a745; padding: 1.5rem; margin: 1rem 0; border-radius: 5px; } .implementation-steps { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.5rem; margin: 2rem 0; } .step-card { background: white; padding: 1.5rem; border-radius: 10px; text-align: center; box-shadow: 0 4px 6px rgba(0,0,0,0.1); border: 2px solid #e9ecef; } .step-number { background: #3498db; color: white; width: 40px; height: 40px; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 1rem; font-weight: bold; } @media (max-width: 768px) { .testing-grid { grid-template-columns: 1fr; } .header h1 { font-size: 2rem; } } </style> </head> <body> <div class="container"> <div class="header"> <h1>๐ง Testing & Implementation</h1> <p>Best practices and testing strategies for reduced motion accessibility</p> </div> <!-- Testing Checklist --> <div class="testing-grid"> <div class="testing-card"> <h3>โ Reduced Motion Testing Checklist</h3> <p>Essential tests to ensure your animations respect user preferences.</p> <div class="checklist"> <div class="checklist-item"> <span style="color: #28a745; font-weight: bold;">โ</span> <span>Test all animations with reduced motion enabled</span> </div> <div class="checklist-item"> <span style="color: #28a745; font-weight: bold;">โ</span> <span>Verify CSS transitions have reduced motion alternatives</span> </div> <div class="checklist-item"> <span style="color: #28a745; font-weight: bold;">โ</span> <span>Check JavaScript animations respect motion preferences</span> </div> <div class="checklist-item"> <span style="color: #28a745; font-weight: bold;">โ</span> <span>Ensure loading states have static alternatives</span> </div> <div class="checklist-item"> <span style="color: #28a745; font-weight: bold;">โ</span> <span>Test hover effects and micro-interactions</span> </div> <div class="checklist-item"> <span style="color: #28a745; font-weight: bold;">โ</span> <span>Verify page transitions and scroll behaviors</span> </div> <div class="checklist-item"> <span style="color: #28a745; font-weight: bold;">โ</span> <span>Check video and GIF content has pause controls</span> </div> <div class="checklist-item"> <span style="color: #28a745; font-weight: bold;">โ</span> <span>Test with actual users who prefer reduced motion</span> </div> </div> </div> <!-- Testing Tools --> <div class="testing-card"> <h3>๐ ๏ธ Testing Tools & Methods</h3> <p>Tools and techniques for testing reduced motion support.</p> <div class="tool-grid"> <div class="tool-card"> <h4>Browser DevTools</h4> <p>Emulate reduced motion in rendering tab</p> </div> <div class="tool-card"> <h4>OS Settings</h4> <p>Test with actual system preferences</p> </div> <div class="tool-card"> <h4>axe-core</h4> <p>Automated accessibility testing</p> </div> <div class="tool-card"> <h4>Lighthouse</h4> <p>Accessibility audits and best practices</p> </div> </div> </div> </div> <!-- Browser Testing --> <div class="testing-card"> <h3>๐ Browser DevTools Testing</h3> <p>Using browser developer tools to test reduced motion support.</p> <div class="browser-demo"> <span style="color: #7f8c8d;">// Chrome/Edge DevTools - Rendering Tab</span><br> 1. Press F12 to open DevTools<br> 2. Press Ctrl+Shift+P (Cmd+Shift+P on Mac)<br> 3. Type "Show Rendering" and select it<br> 4. In the Rendering tab, find "Emulate CSS media feature prefers-reduced-motion"<br> 5. Select "reduce" from the dropdown<br><br> <span style="color: #7f8c8d;">// Firefox Developer Tools</span><br> 1. F12 โ Inspector tab<br> 2. Click "Toggle Accessibility Features" in toolbar<br> 3. Check "prefers-reduced-motion"<br> 4. Use "Accessibility" tab for detailed analysis </div> </div> <!-- Implementation Steps --> <div class="testing-card"> <h3>๐ Implementation Steps</h3> <p>Step-by-step guide to implementing reduced motion support.</p> <div class="implementation-steps"> <div class="step-card"> <div class="step-number">1</div> <h4>Audit Existing Animations</h4> <p>Identify all animations, transitions, and motion effects in your application</p> </div> <div class="step-card"> <div class="step-number">2</div> <h4>Add CSS Media Queries</h4> <p>Wrap animations in @media (prefers-reduced-motion: reduce) queries</p> </div> <div class="step-card"> <div class="step-number">3</div> <h4>Update JavaScript</h4> <p>Add motion preference checks to JavaScript animations</p> </div> <div class="step-card"> <div class="step-number">4</div> <h4>Provide Alternatives</h4> <p>Create static alternatives for essential animations</p> </div> <div class="step-card"> <div class="step-number">5</div> <h4>Test Thoroughly</h4> <p>Test with reduced motion enabled on different devices and browsers</p> </div> <div class="step-card"> <div class="step-number">6</div> <h4>User Testing</h4> <p>Get feedback from users who prefer reduced motion</p> </div> </div> </div> <!-- Best Practices --> <div class="testing-card"> <h3>๐ Best Practices</h3> <p>Essential guidelines for implementing reduced motion accessibility.</p> <div class="best-practices"> <h4>Do's for Reduced Motion:</h4> <ul style="margin: 1rem 0; padding-left: 1.5rem;"> <li>Use the prefers-reduced-motion media query for all animations</li> <li>Provide meaningful alternatives to essential animations</li> <li>Test with actual reduced motion settings enabled</li> <li>Consider providing a manual toggle for motion preferences</li> <li>Use progressive enhancement - start with no motion</li> <li>Document your animation accessibility approach</li> </ul> </div> <div class="testing-demo"> <h4>Common Pitfalls to Avoid:</h4> <ul style="margin: 1rem 0; padding-left: 1.5rem;"> <li>Forgetting to test with reduced motion enabled</li> <li>Relying on motion to convey important information</li> <li>Using auto-playing videos without pause controls</li> <li>Implementing complex parallax effects without alternatives</li> <li>Ignoring scroll-linked animations</li> <li>Overlooking micro-interactions and hover states</li> </ul> </div> </div> <!-- Code Examples --> <div class="testing-card"> <h3>๐ป Complete Implementation Example</h3> <p>A comprehensive reduced motion implementation pattern.</p> <div class="browser-demo"> <span style="color: #7f8c8d;">// Comprehensive reduced motion implementation</span><br> <span style="color: #9b59b6;">const</span> motionPreference = <span style="color: #3498db;">window</span>.<span style="color: #3498db;">matchMedia</span>(<span style="color: #2ecc71;">'(prefers-reduced-motion: reduce)'</span>);<br><br> <span style="color: #7f8c8d;">// CSS-in-JS example</span><br> <span style="color: #9b59b6;">const</span> styles = {<br> <span style="color: #3498db;">animation</span>: motionPreference.matches ? <span style="color: #2ecc71;">'none'</span> : <span style="color: #2ecc71;">'fadeIn 0.5s ease'</span>,<br> <span style="color: #3498db;">transition</span>: motionPreference.matches ? <span style="color: #2ecc71;">'none'</span> : <span style="color: #2ecc71;">'all 0.3s ease'</span><br> };<br><br> <span style="color: #7f8c8d;">// Listen for preference changes</span><br> motionPreference.<span style="color: #3498db;">addEventListener</span>(<span style="color: #2ecc71;">'change'</span>, (e) => {<br> <span style="color: #9b59b6;">if</span> (e.matches) {<br> <span style="color: #3498db;">document</span>.<span style="color: #3498db;">documentElement</span>.<span style="color: #3498db;">classList</span>.<span style="color: #3498db;">add</span>(<span style="color: #2ecc71;">'reduced-motion'</span>);<br> } <span style="color: #9b59b6;">else</span> {<br> <span style="color: #3498db;">document</span>.<span style="color: #3498db;">documentElement</span>.<span style="color: #3498db;">classList</span>.<span style="color: #3498db;">remove</span>(<span style="color: #2ecc71;">'reduced-motion'</span>);<br> }<br> });<br><br> <span style="color: #7f8c8d;">// Global reduced motion class</span><br> <span style="color: #9b59b6;">.reduced-motion</span> * {<br> <span style="color: #3498db;">animation-duration</span>: <span style="color: #2ecc71;">0.01ms</span> <span style="color: #e74c3c;">!important</span>;<br> <span style="color: #3498db;">animation-iteration-count</span>: <span style="color: #2ecc71;">1</span> <span style="color: #e74c3c;">!important</span>;<br> <span style="color: #3498db;">transition-duration</span>: <span style="color: #2ecc71;">0.01ms</span> <span style="color: #e74c3c;">!important</span>;<br> <span style="color: #3498db;">scroll-behavior</span>: <span style="color: #2ecc71;">auto</span> <span style="color: #e74c3c;">!important</span>;<br> } </div> </div> </div> </body> </html>
Practical Applications & Best Practices
โ Do's for Reduced Motion
- Use CSS media queries for all animations and transitions
- Provide static alternatives for essential animations
- Test with actual reduced motion settings enabled
- Consider a manual toggle for motion preferences
- Use progressive enhancement principles
- Document your animation accessibility approach
โ Don'ts for Reduced Motion
- Don't rely on motion to convey important information
- Avoid auto-playing videos without pause controls
- Don't implement complex parallax without alternatives
- Avoid scroll-jacking and forced animations
- Don't forget to test micro-interactions
- Avoid rapid flashing or strobing effects
๐ก Pro Tips for Reduced Motion
Development:
- Use CSS custom properties for easy motion toggling
- Implement reduced motion detection in JavaScript
- Create a global reduced motion CSS class
- Use feature detection for progressive enhancement
- Test with multiple browsers and devices
Design:
- Design static alternatives for all animations
- Consider instant state changes instead of transitions
- Use color and typography to replace motion cues
- Provide clear loading states without animation
- Test designs with reduced motion enabled
Ready to Implement Reduced Motion? ๐ฌ
Start creating accessible animations that respect user preferences and prevent motion sickness. Remember: good motion design isn't about removing all animation - it's about providing appropriate alternatives that work for everyone.