Level AAA

Removes the general and red flash thresholds and the small-area exemption that 2.3.1 relies on -- any flash above three per second fails, regardless of brightness, hue, or size.

2.3.2 Three Flashes

In Plain Language

2.3.2 Three Flashes (Level AAA) is the strict version of 2.3.1 Three Flashes or Below Threshold (Level A). 2.3.1 lets content flash more than three times per second as long as the flash stays under the general and red flash thresholds, or the affected area is small enough. 2.3.2 deletes both escape hatches: no content may flash more than three times in any one-second period, period[1].

The only carve-out at AAA is a fine, balanced pattern (white noise, sub-0.1-degree checkerboards) that does not behave like a flash in the visual system[1]. Every other flash source -- a blinking icon, a strobe transition in a hero video, a rapid opacity toggle on a notification badge -- is in scope regardless of size or brightness.

Why It Matters

  • Photosensitive epilepsy seizures are triggered by luminance or saturated-red oscillation in the 3-to-60 Hz range. 2.3.1's general and red flash thresholds model a "safe enough for most viewers" envelope; 2.3.2 targets the tail of that distribution, where individual sensitivity, viewing distance, or fullscreen playback pushes the risk back up[1].
  • 2.3.1's small-area exemption assumes the flashing region occupies a small fraction of the central 10 degrees of the visual field. That assumption breaks when the user zooms the viewport, watches fullscreen, or holds a phone close. 2.3.2 removes the area condition so the content is safe across all of those viewing contexts.
  • This is the safety bar to meet for content that targets photosensitive users directly: educational material about epilepsy, health-portal content for users with a diagnosis, games and media intended for fullscreen playback, and any venue where the reader cannot be assumed to be looking at a small pop-up on a large screen.
  • Flashing above three per second also drives migraine auras and vestibular symptoms in users who do not have epilepsy. The mechanism is different but the remediation is the same: do not ship the flash.

Examples

Do: Use smooth transitions instead of flashing

Notification using a smooth fade:

transition: opacity 0.5s ease-in-out;

/* No abrupt brightness changes */

✔ Gradual opacity transitions are not flashes and are safe for all users

<!-- Safe: smooth fade animation -->
<style>
  .notification {
    transition: opacity 0.5s ease-in-out;
  }
  .notification.show {
    opacity: 1;
  }
  .notification.hide {
    opacity: 0;
  }
</style>

<div class="notification show" role="status">
  You have new messages
</div>
Do: Use a static icon or color change for alerts

Error state uses a steady red border -- no flashing:

border: 2px solid #dc2626;

/* Persistent visual change, not a flash */

✔ Static color changes communicate urgency without any flashing

<!-- Safe: static visual change, no animation -->
<style>
  .input-error {
    border: 2px solid #dc2626;
    background: #fef2f2;
  }
</style>

<label for="email">Email address</label>
<input id="email" class="input-error"
  aria-invalid="true"
  aria-describedby="email-err">
<p id="email-err" role="alert">
  Please enter a valid email address
</p>
Don't: Use a blinking cursor or indicator (even if small)

Blinking notification badge:

animation: blink 0.2s step-end infinite;

/* Flashes 5 times per second */

✘ Even a small element flashing more than 3 times/second fails 2.3.2 -- no size exception applies

Don't: Auto-play video with rapid flash sequences

Hero video with strobe-style transitions:

<video autoplay muted loop>

<source src='hero-reel.mp4'>

</video>

✘ Video with rapid scene cuts exceeds three flashes per second -- no threshold exception at AAA

How to Fix It

  1. Cut the flash, do not clamp it. The most reliable path to 2.3.2 is to eliminate flashing entirely: replace blink / strobe / rapid-toggle effects with fades, slides, or static state changes. Keeping a flash under the limit only works if you can guarantee the rate never drifts; deleting the flash removes the whole failure mode.
  2. If a flash must exist, cap it at three complete light-dark cycles per second in any one-second window. Measure across the full duration of the animation or video, not just the average rate -- 2.3.2 is failed by any one-second slice that exceeds the limit, not by the overall mean[1].
  3. Analyse recorded video with a harmonised tool. Run prerecorded video through the Trace Center Photosensitive Epilepsy Analysis Tool (PEAT) or an equivalent and fix any segment it flags before publishing. Visual inspection is not a substitute; the thresholds are defined in luminance and red-saturation terms a human viewer cannot reliably estimate.
  4. Audit CSS keyframe animations for short, stepped cycles. Animations using step-end, steps(), or @keyframes with sub-333ms cycles on opacity, background, or visibility are the common failure pattern. Replace them with eased transitions or a single state change.
  5. Honour prefers-reduced-motion as defence in depth, not as the fix. Reduced-motion is a user preference for vestibular and attention-related needs -- it does not absolve flashing content for users who have not set the preference. Ship content that passes 2.3.2 unconditionally, and then also respect prefers-reduced-motion.
  6. Check cross-cite 2.3.1. Passing 2.3.2 automatically passes 2.3.1. If a product decision forces you to drop to the 2.3.1 (Level A) bar, document which exemption you are relying on (general flash threshold, red flash threshold, or small-area) and how each frame was measured against it.

References

  1. [1] W3C (2023). Understanding Success Criterion 2.3.2: Three Flashes. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/three-flashes.html