🎬 Animation & Motion Principles

Animation and motion can cause significant issues for users with vestibular disorders, migraines, epilepsy, and sensory sensitivities. Respecting user preferences and providing controls is essential for inclusive design.

Design Guidelines

Principle Description Recommendation
Respect User Preferences Honor system settings Use prefers-reduced-motion media query
Avoid Flashing Content Prevent seizures Flash rate below 3 times per second
Provide Controls Allow user control Pause/stop buttons for animations, videos, carousels
Avoid Unexpected Animation Prevent surprise Don't trigger animation without user action
Minimize Parallax Reduce vestibular issues Use sparingly or provide alternative
Smooth Transitions Avoid jarring changes Use eased transitions instead of instant changes

CSS Implementation

/* Respect user's reduced motion preference */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Smooth transitions */
.smooth-transition {
  transition: all 0.3s ease-in-out;
}

/* Controllable animation */
.animated-element {
  animation: fadeIn 0.5s ease-out;
}

.animated-element.paused {
  animation-play-state: paused;
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Avoid parallax for sensitive users */
@media (prefers-reduced-motion: reduce) {
  .parallax-element {
    transform: none !important;
  }
}

Tailwind CSS Classes

<div className="transition-all duration-300 ease-in-out
  motion-reduce:transition-none motion-reduce:duration-0">
  Content with smooth transitions
</div>

<div className="animate-fade-in motion-reduce:animate-none">
  Animated content that respects preferences
</div>

React Component

interface AnimatedCardProps {
  children: React.ReactNode;
  autoPlay?: boolean;
}

export function AnimatedCard({
  children,
  autoPlay = false,
}: AnimatedCardProps) {
  const [isPaused, setIsPaused] = useState(!autoPlay);
  const [prefersReducedMotion, setPrefersReducedMotion] = useState(false);

  useEffect(() => {
    const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
    setPrefersReducedMotion(mediaQuery.matches);

    const handler = (e: MediaQueryListEvent) =>
      setPrefersReducedMotion(e.matches);
    mediaQuery.addEventListener("change", handler);
    return () => mediaQuery.removeEventListener("change", handler);
  }, []);

  const showAnimation = !prefersReducedMotion && !isPaused;

  return (
    <div
      className={`
        card bg-base-100 border border-base-300 p-6
        ${showAnimation ? "animate-fade-in" : ""}
      `}
    >
      <div className="flex justify-between items-start">
        <div>{children}</div>
        {!prefersReducedMotion && (
          <button
            onClick={() => setIsPaused(!isPaused)}
            className="btn btn-ghost btn-sm btn-circle"
            aria-label={isPaused ? "Play animation" : "Pause animation"}
          >
            {isPaused ? (
              <Play className="w-4 h-4" />
            ) : (
              <Pause className="w-4 h-4" />
            )}
          </button>
        )}
      </div>
    </div>
  );
}

Platform Settings for Reduced Motion

Platform Settings Path
Windows 10 Settings > Ease of Access > Display > Show animations in Windows
Windows 11 Settings > Accessibility > Visual effects > Animation effects
macOS System Preferences > Accessibility > Display > Reduce motion
iOS Settings > General > Accessibility > Reduce Motion
Android 9+ Settings > Accessibility > Remove animations

Seizure Prevention Guidelines

  • Flash Rate: Keep below 3 flashes per second
  • Flash Area: Limit to small portion of screen
  • Contrast: Avoid high-contrast flashing
  • Red Flashing: Particularly dangerous - avoid entirely
  • Duration: Limit flashing sequences to brief periods

Checklist

  • prefers-reduced-motion is respected
  • No content flashes more than 3 times per second
  • Animations have pause/stop controls
  • Animations don't auto-play unexpectedly
  • Parallax effects are minimized or optional
  • Transitions are smooth, not jarring
  • Carousel has visible pause controls

Last updated: 2026-10-20

Menu
Loading