Skip to content

Conversation

@tahmidbintaslim
Copy link

@tahmidbintaslim tahmidbintaslim commented Dec 12, 2025

Summary

Fixes #4298

Problem

Loading components (spinner, dots, ring, ball, bars, infinity) use animated SVGs with SMIL animations as mask-image. These animations continue to run even when prefers-reduced-motion: reduce is set because SMIL animations aren't affected by CSS media queries.

This creates unnecessary rapid motion for users who have requested reduced motion due to vestibular disorders, epilepsy, or other motion sensitivities.

Solution

Added a @media (prefers-reduced-motion: reduce) block that provides slowed-down versions (4x slower) of all animations instead of disabling them completely. This approach:

  1. Respects the user's preference - Motion is significantly reduced
  2. Maintains usability - Loading indicators still visually communicate "loading" state
  3. Follows best practices - prefers-reduced-motion: reduce means "reduce" not "eliminate"

Animation Duration Changes

Component Original Reduced Motion
.loading / .loading-spinner rotation 2s 8s
.loading / .loading-spinner dasharray 1.5s 6s
.loading-dots 1.05s 4.2s
.loading-ring 1.8s 7.2s
.loading-ball 0.8s 3.2s
.loading-bars 0.8s 3.2s
.loading-infinity 2s 8s

How to test

  1. Open Chrome DevTools → Rendering panel → Enable "Emulate CSS media feature prefers-reduced-motion: reduce"
  2. View any loading component - it should animate at 1/4 speed

Or set reduced motion in your OS:

  • macOS: System Preferences → Accessibility → Display → Reduce motion
  • Windows: Settings → Ease of Access → Display → Show animations

Notes

  • Other components (carousel, collapse, dropdown) already respect prefers-reduced-motion correctly via @media (prefers-reduced-motion: no-preference) blocks
  • This is a pure CSS fix, no JavaScript required
  • The 4x slowdown factor can be adjusted if a different ratio is preferred

Add @media (prefers-reduced-motion: reduce) block to replace animated SVG
mask-images with static equivalents for all loading variants (spinner, dots,
ring, ball, bars, infinity).

This respects user accessibility preferences for reduced motion by showing
static visuals instead of animated SMIL SVGs when the user has enabled
reduced motion in their OS or browser settings.
Copilot AI review requested due to automatic review settings December 12, 2025 09:48
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes issue #4298 where loading component animations continue to run even when users have prefers-reduced-motion: reduce enabled. The fix addresses an accessibility issue for users with motion sensitivities by replacing animated SMIL SVGs with static equivalents when reduced motion is requested.

Key Changes:

  • Added @media (prefers-reduced-motion: reduce) block to override animated SVG masks with static versions
  • Implemented static SVG representations for all six loading variants (spinner, dots, ring, ball, bars, infinity)
  • Static visuals maintain the same visual appearance as their animated counterparts, just without motion

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Owner

@saadeghi saadeghi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR.

I don't think this is a good idea to completely disable the animations. With prefers-reduced-motion: reduce the loadings are not going to be understandable. mostly they will look like static circle icons which won't communicate to the user that it's an indicator that something is "loading".

prefers-reduced-motion: reduce should be about reducing the motion, not "disabling" it completely. In this case, slowing down the animation would be more helpful that disabling the animations.

…ed-motion

Per maintainer feedback, completely disabling animations makes loading
indicators unrecognizable. This update slows animations by 4x instead:

- .loading/.loading-spinner: 2s→8s rotation, 1.5s→6s dasharray
- .loading-dots: 1.05s→4.2s
- .loading-ring: 1.8s→7.2s  
- .loading-ball: 0.8s→3.2s
- .loading-bars: 0.8s→3.2s
- .loading-infinity: 2s→8s

This reduces motion while preserving the visual indication that
something is loading.
@tahmidbintaslim
Copy link
Author

tahmidbintaslim commented Dec 15, 2025

@saadeghi Thanks for the feedback! You're absolutely right - prefers-reduced-motion: reduce should reduce motion, not eliminate it completely.

I've updated the PR to slow down the animations by 4x instead of replacing them with static images. This way:

  • Loading indicators still clearly communicate "loading" state
  • Motion is significantly reduced for users who need it
  • The change is consistent with the spec's intent

Let me know if you'd prefer a different slowdown factor (e.g., 2x or 3x instead of 4x).

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@media (prefers-reduced-motion: reduce) {
.loading,
.loading-spinner {
@layer daisyui.l1.l2 {
Copy link

Copilot AI Dec 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The layer specificity is inconsistent with the original .loading class definition. The original .loading class at line 2 uses @layer daisyui.l1.l2.l3, but this reduced-motion override uses @layer daisyui.l1.l2. This means the reduced-motion styles may not have the correct specificity to override the original styles. The layer should be daisyui.l1.l2.l3 to match the original .loading definition.

Copilot uses AI. Check for mistakes.
Changed .loading from @layer daisyui.l1.l2 to @layer daisyui.l1.l2.l3
to match the original class definition and ensure proper override.
@tahmidbintaslim
Copy link
Author

tahmidbintaslim commented Dec 15, 2025

Fixed the layer specificity issue in commit e839bc6.

  • .loading now uses @layer daisyui.l1.l2.l3 (matching its original definition)
  • .loading-spinner stays at @layer daisyui.l1.l2 (matching its original definition)

The selectors are now separated to use the correct layer for each class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: A11y: Components ignore prefers-reduced-motion (carousel, loading, collapse, dropdown)

2 participants