WCAG 2.3.1 — Three Flashes or Below Threshold
Anything flashing more than three times per second can trigger seizures in people with photosensitive epilepsy. The risk isn't theoretical — there are documented cases of broadcasts hospitalising hundreds of people.
What this requires
Content must not contain anything that flashes more than three times in any one-second period, unless the flashing area is small and the flash stays below the general and red flash thresholds defined in WCAG. The conservative reading: don't flash more than three times per second, full stop, unless you've measured the flash area and luminance against the technical thresholds.
How AI coding tools fail this
When asked for "an attention-grabbing loading state" or "a high-energy
hero animation", AI tools sometimes generate strobing colour
transitions, rapid-fire opacity or background keyframes, or
flashing notification badges. The visual reads as energetic; the
medical risk for photosensitive users is real.
The second pattern: GIFs and short videos with rapid flash sequences embedded with no warning and no autoplay control. Even when the flash isn't in the page CSS, embedding a 15Hz strobe loop is the same failure with a different delivery method.
The third: chart libraries with default animations that flash data points in rapid sequence as the user interacts with filters. The flashing is incidental but real.
Edge cases
- The general flash threshold is roughly: a flash with a relative luminance change of less than 0.1, or covering less than 25% of the 10° visual field at typical viewing distance, is below threshold. Most teams should treat anything over 3 Hz as a fail rather than trying to measure the threshold.
- Red flashing is more dangerous than other colours and has a stricter threshold.
prefers-reduced-motiondoesn't satisfy this criterion alone — the criterion is about absolute danger, not user preference — but it's a good companion.- Test with PEAT (the Photosensitive Epilepsy Analysis Tool from the Trace Center) when in doubt.
- 2.3.1 is A; 2.3.2 is AAA. The difference: 2.3.2 removes the small-area exception entirely.
How Jeikin handles this
This criterion is genuinely hard to verify statically — frame-rate analysis requires runtime measurement. Jeikin's guided review uses PEAT on flagged components and records the result. The scanner flags CSS animations with durations under 333ms (the 3 Hz floor) as leading indicators.