Website publishing

Flashing Animations and Motion Sickness: Website Safety Explained

Photosensitive epilepsy and motion sensitivity explained carefully, what WCAG requires, and a working HTML and CSS example with prefers-reduced-motion and a pause control.

PlayKovo Team6 min read
Games currently available on PlayKovo. Open a title to see its current listing.

Animation makes a site feel alive, but for some visitors it is a real problem. Rapid flashing can trigger seizures in people with photosensitive epilepsy, and large moving areas can cause dizziness and nausea in people with vestibular disorders. Most of the risk can be removed with a few rules and about ten lines of CSS.

This guide explains the two risks accurately, what the Web Content Accessibility Guidelines (WCAG) require, how to support prefers-reduced-motion, and includes a working HTML/CSS example. It is general information, not medical or legal advice.

Two different risks

Flashing and photosensitive epilepsy

The Epilepsy Society (UK) says around 3 percent of people with epilepsy have photosensitive epilepsy, where seizures are triggered by flashing lights or high-contrast patterns. Most people who develop it are between 7 and 19 years old. Triggers include flashing or flickering light, with the 16 to 25 flashes per second range most likely to trigger seizures, high-contrast moving patterns such as stripes and checks, and flashing images on screens and in games, including autoplaying videos and GIFs. Tiredness, excitement, sitting close to the screen and a dark room can raise the risk. It is not common, but the effect is serious, and you cannot tell from the outside who is affected.

Motion and vestibular sensitivity

Large or continuous movement on screen, such as parallax scrolling, zooming, spinning or full-page transitions, can cause dizziness, nausea and headaches for people with vestibular (inner ear) disorders and for others who are sensitive to motion. This is a comfort and health issue, not a seizure risk, and it needs a different fix: letting people turn motion down.

Blinking is not the same as flashing. WCAG notes that blinking is a distraction issue, while flashing can trigger seizures, so it cannot be allowed even briefly.

What WCAG requires

CriterionLevelRequirement
2.3.1 Three Flashes or Below ThresholdANothing flashes more than three times in any one second, or the flash is below the general flash and red flash thresholds
2.3.3 Animation from InteractionsAAAMotion animation triggered by interaction can be disabled, unless essential
2.2.2 Pause, Stop, HideAContent that moves, blinks or scrolls automatically for more than 5 seconds next to other content can be paused, stopped or hidden

Under 2.3.1, content passes if it has no more than three general flashes and/or three red flashes in any one-second period, or if the combined area of flashes stays under a small threshold (0.006 steradians within any 10-degree visual field, about a quarter of that field). A general flash is a change in relative luminance of at least 10 percent where the darker state is below 0.80, and a red flash involves a saturated red transition. W3C also points out that people sitting closer to the screen or using zoom can be affected by areas that otherwise pass, and that people are more sensitive to red flashing.

The practical rule: do not flash. If you cannot avoid a flashing effect (some games and video clips), measure it with a tool such as the Harding test used for broadcast, or remove it.

Where sites go wrong

  • Animated GIF banners and ads with strobing effects.
  • Autoplaying video or hero loops with quick cuts and flashes.
  • Strobing loading screens and "sale" badges that blink.
  • Full-screen transitions, parallax and zoom effects on scroll.
  • Games with flashing hit effects or lightning scenes, which need a warning and a setting to reduce effects.
  • Carousels that move on their own with no pause button.

Supporting prefers-reduced-motion

prefers-reduced-motion is a CSS media feature that reflects the visitor's operating system setting to reduce motion. W3C lists it as a sufficient technique for 2.3.3 (technique C39 for CSS) and advises taking advantage of the reduce motion feature in the operating system. Support is broad in current browsers.

Two common approaches:

  1. Opt-in motion: only animate inside @media (prefers-reduced-motion: no-preference). Safest default, because users who cannot or do not set the preference still get a calmer page.
  2. Opt-out: animate by default and turn motion off inside @media (prefers-reduced-motion: reduce).

Working example

This page has a sliding banner, a hover zoom and a pulsing badge. Motion runs only for visitors without a reduce-motion preference, and an on-page button lets anyone stop it. Save it as an HTML file and open it, then switch your operating system's reduce-motion setting to see the difference.

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Reduced motion example</title>
<style>
  body { font: 1.125rem/1.6 system-ui, sans-serif; margin: 0; padding: 1rem; }
  .banner { overflow: hidden; background: #eef3ff; padding: .75rem 1rem; }
  .banner span { display: inline-block; }
  .card img { display: block; width: 100%; max-width: 320px; }
  .badge { display: inline-block; padding: .2rem .6rem; background: #ffe08a; border-radius: 4px; }

  /* Motion only when the visitor has not asked to reduce it,
     and only when the page is not paused. */
  @media (prefers-reduced-motion: no-preference) {
    html:not(.paused) .banner span { animation: slide 12s linear infinite; }
    html:not(.paused) .card img { transition: transform .3s ease; }
    html:not(.paused) .card:hover img { transform: scale(1.05); }
    html:not(.paused) .badge { animation: pulse 2s ease-in-out 3; } /* 3 gentle pulses, no flashing */
  }
  @keyframes slide { from { transform: translateX(100%); } to { transform: translateX(-100%); } }
  @keyframes pulse { 50% { transform: scale(1.08); } }
</style>
</head>
<body>
  <button id="toggle" type="button" aria-pressed="false">Pause animations</button>
  <div class="banner"><span>Free games every week</span></div>
  <div class="card"><img alt="Game preview" src="preview.jpg"></div>
  <p><span class="badge">New</span> Text stays still and readable.</p>
<script>
  const btn = document.getElementById('toggle');
  btn.addEventListener('click', () => {
    const paused = document.documentElement.classList.toggle('paused');
    btn.setAttribute('aria-pressed', String(paused));
    btn.textContent = paused ? 'Resume animations' : 'Pause animations';
  });
</script>
</body>
</html>

What it demonstrates:

  • Nothing flashes. The pulse scales the badge gently and stops after three repeats.
  • Motion is opt-in with no-preference, so visitors who set reduced motion get a static page.
  • The pause button satisfies the intent of WCAG 2.2.2 for the sliding banner, for everyone, not just people with the OS setting.
  • Meaningful content does not depend on animation.

A global safety net

If you maintain a large site with many animations, this blunt rule reduces them all for visitors who ask. It is widely used, but test your page afterwards, since cutting durations to almost zero can break animations that signal state changes:

@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;
  }
}

Design guidance beyond code

  • Prefer fades and small shifts over large zooms, spins and full-screen sweeps.
  • Avoid parallax on large areas, and do not hijack scrolling.
  • Keep animations short, and let essential state changes show through colour, text or an icon instead of motion.
  • Do not autoplay video with fast cuts. Use a poster image and a play button.
  • For games and video, warn about flashing effects and provide an option to reduce them.
  • Test with the system reduce-motion setting on, on a real phone as well as a desktop.

Checklist

  • Nothing on the site flashes more than three times in a second.
  • No strobing GIFs, ads or loading effects.
  • Motion is wrapped in prefers-reduced-motion.
  • Anything that moves for more than five seconds can be paused.
  • Autoplay is off for video, and audio never starts by itself.
  • Meaning never depends on animation alone.
  • Pages were tested with reduced motion on.

Sources

This article is general information, not medical or legal advice. For related reading, see how to make your website more comfortable for people who read for hours.

We use optional cookies for site analytics and site advertising. You can change your choice later. Privacy policy.