( Operable / WCAG 2.3.1 )
Content flashes more than 3 times per second
What is this issue?
Content on the page flashes (transitions rapidly between a relatively bright and a relatively dark state, or between two contrasting colors) more than three times within any one-second window. WCAG’s general flash threshold is three flashes per second; a stricter red flash threshold applies specifically to transitions involving a saturated, high-contrast red, since red flashing carries a higher seizure risk at the same frequency. A very small flashing area, below roughly 25% of a 10-degree visual field at typical viewing distance, is exempt from the general threshold, but this exemption is narrow and easy to miscalculate; it should not be relied on as a default excuse.
Common sources include a fast CSS opacity or background-color keyframe animation, an embedded GIF with rapid alternating frames, strobe-style effects in video content, and canvas or WebGL-based visual effects that update faster than the eye can smoothly track.
Why does this matter?
Photosensitive epilepsy is triggered by rapid, high-contrast visual changes, and a seizure from web content is a genuine medical emergency, not a metaphorical inconvenience. Unlike most accessibility failures, which degrade an experience, a flash-rate failure can cause direct physical harm to a specific, identifiable population the moment they load the page: there is no graceful degradation here, only a pass or a hazard.
This is why 2.3.1 sits at Level A, the baseline every WCAG conformance level requires, and why RedFlag rates it critical regardless of how small or “just a subtle pulse” the offending element looks in isolation. A marketing team testing a flashing call-to-action banner on a calibrated design monitor has no way to feel the seizure risk it poses to a photosensitive visitor; the risk exists independent of how the effect reads to someone without the condition.
Who is affected?
- Cognitive disabilities: photosensitive epilepsy is a neurological condition triggered by rapid, high-contrast visual patterns; a flash above the threshold can trigger a seizure regardless of whether the visitor has any prior awareness of their own sensitivity.
- Low vision users: even below the seizure threshold, rapid flashing causes measurable discomfort, disorientation, and can trigger migraines for people whose vision conditions make them more sensitive to rapid visual change generally.
What users experience
Renata has photosensitive epilepsy, diagnosed after a seizure in her twenties, and has since learned to close a browser tab immediately at the first sign of rapid flashing rather than risk exposure. She clicks a link to a promotional landing page for a product launch, and an autoplaying background video includes a strobe-light effect timed to a music drop, flashing well above the three-per-second threshold for several seconds before she can react. She has enough warning to look away and close the tab, but the incident leaves her unable to trust that outlet’s other pages without a friend pre-checking them first, and she avoids the brand going forward.
How do I fix it?
Remove the flashing effect, or slow its rate until it measures below three flashes per second across the entire page, not just within a single element, since multiple flashing elements can combine to exceed the threshold even if none does individually. This is the only fix that addresses the actual risk, because there’s no accessible way to “add a warning” to flashing content the way some other WCAG failures allow a workaround; the flash itself is the hazard.
For an existing animation, redesign it around a slower transition (a fade or pulse over one to two seconds instead of a rapid strobe) that preserves the intended visual emphasis without crossing the threshold. For embedded or third-party video content, check the actual flash rate before publishing; don’t assume a video platform’s own content moderation catches this, since flash-rate compliance is a different check from general content moderation. Always pair any remaining animation with a prefers-reduced-motion media query as a second layer of protection, even though it doesn’t substitute for staying under the flash threshold in the first place.
Code Examples
/* Flashes 10 times per second - well above the 3/second threshold */
@keyframes flash {
0%, 100% { opacity: 1; background: #ffffff; }
50% { opacity: 0; background: #d90000; }
}
.alert-banner {
animation: flash 0.1s infinite;
}/* Pulses once every 2 seconds - well under the threshold, same visual intent */
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.75; }
}
.alert-banner {
animation: pulse 2s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
.alert-banner {
animation: none;
}
}The original animation completes a full flash cycle every 0.1 seconds (ten times per second, more than three times the seizure-risk threshold) and switches to a saturated red, compounding the risk. The fixed version stretches the same visual idea (drawing attention to an alert) across a 2-second cycle with a gentler opacity dip, which reads as a calm pulse rather than a strobe, and adds a prefers-reduced-motion fallback as a second layer of protection on top of already being under the threshold.
Common Mistakes
Mistake: “It’s a subtle pulse, not an aggressive strobe, so it’s probably fine.” Seizure risk is a function of measured flash rate and contrast, not subjective visual impression: an effect that reads as gentle to someone without photosensitivity can still measure well above three flashes per second. Measure the actual rate rather than judging by how the animation feels to watch.
Mistake: “We only need to check our own CSS animations, not embedded video.” WCAG 2.3.1 applies to any flashing content the page presents to a visitor, including third-party video, GIFs, and ad creative a publisher doesn’t control the production of. Hosting or embedding flashing content carries the same responsibility as building it directly.
Mistake: “A content warning before the flashing content satisfies the requirement.” Unlike some WCAG failures, a warning does not substitute for staying under the flash threshold; 2.3.1 has no “warn the user first” exception. The only compliant options are removing the flash, slowing it below the threshold, or keeping the flashing area small enough to qualify for the narrow area-based exemption.
Mistake: “Respecting prefers-reduced-motion covers this requirement.” Reduced-motion preferences are an opt-in setting most visitors never enable, while 2.3.1 requires safety for every visitor by default. Treat prefers-reduced-motion as an additional protection layered on top of an already-safe flash rate, never as a substitute for one.
How RedFlag Detects This
Guidance only: RedFlag documents this issue but does not currently flag it; verify manually. RedFlag’s coverage model records criterion 2.3.1’s detection evidence as docs_only. Measuring flash rate accurately requires frame-by-frame visual analysis of rendered content over time, a fundamentally different kind of check from the static DOM inspection RedFlag’s scan engine performs, and no such visual analysis exists in the current detection pipeline.
False negative: every flash-rate failure on a scanned page is a false negative in this sense: a page with a strobing background animation or an embedded flashing video passes every automated RedFlag scan silently, since nothing measures rendered visual output over time. False positive: not applicable, since no automated violation is ever raised for this criterion. Manual step: given the seizure-safety stakes, treat any animation, GIF, or video with rapid, high-contrast transitions as a mandatory manual check before publishing; use a dedicated flash-analysis tool rather than judging by eye, since human perception is not a reliable substitute for a frame-by-frame measurement.
Manual Testing
- Identify every animation, GIF, and embedded or hosted video on the page that includes rapid brightness or color transitions.
- For CSS or JavaScript animations, calculate the flash rate directly from the animation’s timing: a 0.1s full cycle duration produces roughly 10 flashes per second.
- For video and GIF content, use a dedicated flash-analysis tool, such as the Trace Center’s Photosensitive Epilepsy Analysis Tool (PEAT), to measure the actual rendered flash rate and red-flash rate frame by frame; do not judge by eye.
- Confirm the measured rate stays below three general flashes per second and below the stricter red-flash threshold for any saturated-red transitions; if either exceeds the threshold and the flashing area isn’t small enough to qualify for the narrow exemption, the check fails.
- Re-test after any change to animation timing, since a “slight speed increase” during later design iteration can silently push a previously-safe effect back over the threshold.
Related WCAG Success Criteria
2.3.1 Three Flashes or Below Threshold: Content must not flash more than three times in any one-second period, or the flash must stay below the general and red flash thresholds. This rule is a direct check of that measured rate, at the Level A baseline every WCAG conformance level requires.
A stricter Level AAA sibling, 2.3.2 Three Flashes, removes the threshold exceptions entirely and bans any flashing above three times per second outright, relevant context if the product targets AAA conformance, though most organizations only need to satisfy the Level A version this rule documents.
Related Issues
Page contains a blinking or scrolling element shares the same “uncontrolled repeating visual change” root cause as this rule, though blink’s slower toggle rate is a distraction and focus problem under 2.2.2 rather than the seizure-risk concern 2.3.1 addresses; the two criteria commonly get confused, so review both together.
Page has no way to bypass repeated content, Page has no descriptive title, Heading is empty or contains only whitespace, Focus order does not match the visual or DOM order, and Element is skipped in the keyboard focus order are other foundational Operable-principle checks worth running as part of the same audit pass that catches flash-rate risks.
References
- W3C Understanding 2.3.1: Three Flashes or Below Threshold
- Trace Center: Photosensitive Epilepsy Analysis Tool (PEAT)
- WebAIM: Seizure Disorder
Frequently asked questions
Is the 3-flashes-per-second threshold a strict cutoff, or does size and color matter too?
Both matter. WCAG's general flash threshold is three flashes per second for any flashing content, but a stricter "red flash" threshold applies specifically to saturated red transitions, and flashes covering a very small area of the screen are exempt regardless of rate. In practice, treat any rapid, high-contrast flashing as a risk and measure it properly rather than relying on the exemptions.
Does this rule apply to embedded video content, not just CSS animation?
Yes. WCAG 2.3.1 applies to any content that flashes, including video you embed, GIFs, and Canvas or WebGL animations, not only CSS-driven effects. A site is responsible for flash-rate checking third-party video content it chooses to host or embed, even if it did not produce the footage.
What's the difference between 2.3.1 and 2.3.2?
2.3.1 Three Flashes or Below Threshold, the Level A criterion this rule documents, allows flashing below the measured threshold. 2.3.2 Three Flashes, a stricter Level AAA criterion, bans any flashing above three times per second with no threshold exceptions at all. Most sites only need to satisfy the Level A version.
Can I rely on a video platform's own flash-warning system instead of checking myself?
No. A third-party player showing a general content warning does not verify the flash rate against WCAG's specific measurement method, and does not exempt your page from the requirement. If you embed or host flashing content, the responsibility for checking the actual flash rate stays with the page publishing it.
Does prefers-reduced-motion automatically satisfy this requirement?
No, they are separate concerns. Respecting prefers-reduced-motion reduces or removes animation for users who opt into that OS-level setting, but 2.3.1 requires content to stay below the flash threshold for every visitor by default, whether or not they have that preference set. A flashing effect above the threshold fails 2.3.1 even if it politely turns off for users who requested reduced motion.