WCAG Success Criteria · Level AAA
WCAG 2.3.2: Three Flashes
WCAG 2.3.2 requires that web pages contain no content that flashes more than three times in any one-second period, with no exception for small or low-contrast flashes. This stricter AAA criterion protects users with photosensitive epilepsy and other seizure disorders from potentially life-threatening neurological reactions.
- Level AAA
- Wcag
- Wcag 2 2 aaa
- Operable
- Accessibility
What This Rule Means
WCAG 2.3.2 Three Flashes is a Level AAA success criterion under the Operable principle. It states that web pages must not contain anything that flashes more than three times in any one-second period. Unlike its Level AA counterpart (2.3.1 Three Flashes or Below Threshold), this criterion allows no exceptions for small flashing areas or flashes that fall below the general flash and red flash thresholds. The rule is absolute: if content flashes more than three times per second, it fails, regardless of size, color, or contrast.
A flash is defined by WCAG as a pair of opposing changes in relative luminance that can cause seizures in some people. More practically, any visible on-off blinking, strobe-like animation, rapidly cycling images, or flickering video that completes more than three full cycles per second falls within the scope of this rule. The term "three flashes" refers to three complete oscillations — meaning content that alternates between a lighter and darker state three times within a single second.
The affected content types are broad and include animated GIFs, CSS animations using @keyframes, JavaScript-driven DOM updates that cause rapid visual toggling, HTML5 Canvas animations, embedded video content, SVG animations, and third-party ad networks or widgets that embed animated media. Even subtle flickering in scrolling marquee text or rapidly updating data visualizations can trigger this criterion if the rate exceeds three flashes per second.
A pass under 2.3.2 means the page contains no flashing content at all that exceeds the three-flashes-per-second threshold. A fail occurs any time any portion of the page — regardless of how small the area is — flashes more than three times within any one-second window. There is no safe-area exception under this criterion, which is what distinguishes it from 2.3.1. A tiny blinking cursor, an animated loading spinner, or a rapidly cycling advertisement banner could all constitute failures if they flash at frequencies exceeding 3 Hz.
Why It Matters
Photosensitive epilepsy affects approximately 1 in 4,000 people globally, but the total population susceptible to some form of photosensitive neurological response — including photosensitive migraines, vestibular disorders, and non-epileptic photosensitivity — is significantly larger. For these individuals, exposure to rapidly flashing content on a screen is not a mere annoyance: it can trigger grand mal seizures, loss of consciousness, injury, or in rare cases death. Unlike many accessibility barriers that degrade user experience, flashing content presents an acute safety hazard.
Consider a practical scenario: a Turkish news website embeds a live ticker with an animated highlight effect that pulses at 8 Hz to draw attention to breaking news. A user with photosensitive epilepsy opens the page on their phone while commuting. Within seconds, the rapid flicker triggers a focal seizure, causing the person to drop their phone and lose muscle control momentarily. They had no warning, no way to disable the effect in advance, and no recourse. This scenario is entirely preventable by limiting flash rates to three per second or fewer — or by eliminating flashing content altogether, as 2.3.2 demands.
Beyond the neurological safety dimension, complying with this criterion also benefits users with vestibular disorders (who experience dizziness, nausea, or disorientation from motion), users with migraines triggered by visual patterns, and users with attention-deficit disorders who find rapidly flashing content impossible to ignore or work around. Reducing or eliminating flashing content also tends to improve perceived page professionalism and reduce user abandonment rates, as many users — disabled or not — find aggressive animations irritating.
From an SEO and performance perspective, eliminating heavy animations and rapid CSS transitions reduces CPU and GPU load, improving Core Web Vitals scores such as Total Blocking Time and Cumulative Layout Shift, both of which are Google ranking signals.
Related Axe-core Rules
WCAG 2.3.2 requires manual testing. No automated axe-core rule maps directly to this criterion, and this is intentional — here is why automated tools cannot reliably catch violations:
- Manual testing required — Flash rate detection: Automated accessibility scanners inspect the static DOM and CSS at a single point in time. They cannot observe how content behaves over a full second of animation playback, measure the luminance oscillation frequency of a video or animated GIF, or evaluate the frame rate of a Canvas animation. The flash rate is a temporal property that requires real-time observation, making it fundamentally beyond the reach of static analysis tools like axe-core. A human tester — or specialized photosensitivity analysis tools such as the Photosensitive Epilepsy Analysis Tool (PEAT) — must review animated content in motion to determine whether it exceeds the three-flashes-per-second threshold.
- Manual testing required — Third-party and embedded content: Advertisements, embedded videos, social media widgets, and iframes may inject animated content that axe-core cannot analyze, because it operates within the same-origin policy constraints of the browser. A tester must manually observe all embedded and third-party content during playback to assess compliance.
- Manual testing required — JavaScript-driven animations: Rapidly toggling CSS classes, updating canvas pixels, or manipulating SVG elements via JavaScript at high frequency can produce flashing effects that are invisible to a static DOM snapshot. Testers must run the page in a live browser, observe all animated states, and time the flash cycles manually or with frame-rate analysis tools.
How to Test
- Run an automated scan as a baseline: Use axe DevTools, Lighthouse, or the Accsible widget's built-in audit to identify any flagged animation-related issues. While no rule directly maps to 2.3.2, these tools may surface related warnings about CSS animations or ARIA live regions that update rapidly. Note any flagged items, but understand that a clean automated report does not confirm 2.3.2 compliance.
- Identify all animated content manually: Load the page in a browser and observe it for at least 30 seconds without interacting. Note every element that blinks, flashes, animates, or changes visual state repeatedly. Include loading spinners, banners, hero animations, auto-playing videos, animated backgrounds, and any third-party widgets. Create an inventory of these elements.
- Use the Photosensitive Epilepsy Analysis Tool (PEAT): For video content or screen recordings of animations, use PEAT (a free tool from the Trace Research and Development Center) to analyze the footage frame by frame. PEAT will flag any sequences that exceed flash thresholds and report both the general flash threshold and the red flash threshold. A 2.3.2 failure is any flash exceeding three per second regardless of other thresholds.
- Measure CSS and JavaScript animation rates: Open browser DevTools (Chrome or Firefox) and use the Performance tab to record a 5-second session while animations play. Inspect the flame graph for rapidly repeating paint or layout operations. You can also open the Animations panel in Chrome DevTools to see running animations and their durations — divide 1000ms by the animation duration to calculate Hz.
- Test with NVDA + Firefox, VoiceOver + Safari, and JAWS + Chrome: Screen reader users are not exempt from photosensitivity. Launch each screen reader and navigate to the page normally. If any content that flashes visually is also presented in a way that causes rapid screen refreshes (such as a live region announcing every frame of a counter), document this. Visual flashing remains a violation even for screen reader users because they may have some functional vision.
- Verify third-party and embedded content: Scroll through all iframes, embedded social media posts, advertisement slots, and video players. Manually play any autoplay-disabled videos and observe for rapid flicker. Check animated GIFs by right-clicking and inspecting frame data in an image editor or the browser's Network tab to estimate frame rate.
- Repeat testing across devices and browsers: Some animations run at different speeds on mobile versus desktop due to hardware acceleration differences. Test on both a desktop browser and a mobile device (iOS Safari and Android Chrome) to confirm consistent compliance.
How to Fix
CSS Keyframe Animation Flashing Too Fast — Incorrect
<!-- A badge that flashes to draw attention, completing 8 cycles per second -->
<style>
@keyframes flash-badge {
0%, 49% { background-color: red; }
50%, 100% { background-color: transparent; }
}
.alert-badge {
animation: flash-badge 0.125s infinite; /* 8 Hz — far exceeds 3 per second */
}
</style>
<span class='alert-badge'>NEW</span>
CSS Keyframe Animation Flashing Too Fast — Correct
<!-- Animation slowed to complete fewer than 3 cycles per second -->
<style>
@keyframes flash-badge {
0%, 49% { background-color: red; }
50%, 100% { background-color: transparent; }
}
.alert-badge {
animation: flash-badge 0.4s infinite; /* ~2.5 Hz — safely below the 3 Hz threshold */
}
</style>
<span class='alert-badge'>NEW</span>
<!-- Better still: remove the animation entirely and use a static high-contrast badge -->
JavaScript DOM Toggle Causing Rapid Flicker — Incorrect
<!-- Script toggles visibility 10 times per second to simulate a strobe effect -->
<div id='strobe-element' style='width:200px;height:200px;background:white;'></div>
<script>
setInterval(function() {
var el = document.getElementById('strobe-element');
el.style.background = el.style.background === 'white' ? 'black' : 'white';
}, 100); /* Fires every 100ms = 10 flashes per second -- a serious seizure risk */
</script>
JavaScript DOM Toggle Causing Rapid Flicker — Correct
<!-- Removed the rapid toggle entirely; convey state change through text or icon instead -->
<div id='status-element' style='width:200px;height:200px;background:#005fcc;'>
<p style='color:white;padding:1rem;'>System Active</p>
</div>
<!-- If animation is genuinely needed, keep it well under 3 Hz and prefer opacity/color
transitions over high-contrast luminance switches -->
Animated GIF with High Frame Rate — Incorrect
<!-- An animated GIF advertisement that cycles through frames at 10 fps -->
<img src='promo-flash.gif' alt='Special offer — 50% off this weekend only'>
<!-- The GIF's internal frame delay is set to 10ms per frame, creating rapid flicker -->
Animated GIF with High Frame Rate — Correct
<!-- Replace the animated GIF with a static image, or re-export the GIF
with a minimum frame delay of 334ms per frame (3 fps or slower) -->
<img src='promo-static.png' alt='Special offer — 50% off this weekend only'>
<!-- If motion must be preserved, use a CSS animation with prefers-reduced-motion support -->
<picture>
<source srcset='promo-static.png' media='(prefers-reduced-motion: reduce)'>
<img src='promo-slow.gif' alt='Special offer — 50% off this weekend only'>
</picture>
Common Mistakes
- Assuming the "small area" exception from 2.3.1 applies to 2.3.2: WCAG 2.3.1 allows flashing content that occupies less than 25% of a 10-degree visual field. WCAG 2.3.2 has no such exception — a tiny blinking cursor or a small loading dot that flashes more than three times per second is a full violation at AAA level.
- Setting CSS animation-duration to values like 0.1s or 0.2s without calculating the resulting flash rate: A 0.1s animation that oscillates between two states completes 10 cycles per second (10 Hz). Divide 1 by the duration in seconds to get Hz; ensure the result is 3 or below.
- Embedding third-party ad scripts without reviewing animation behavior: Ad networks frequently serve animated creatives with high flash rates optimized for click-through, not accessibility. Always audit third-party content using PEAT or manual frame inspection before deploying.
- Using
setIntervalorrequestAnimationFrameloops to toggle CSS classes rapidly for loading or progress indicators: Any JavaScript loop that changes an element's luminance or visibility more than three times per second creates a 2.3.2 violation, even if the effect looks subtle in normal viewing conditions. - Not testing animated SVGs and Canvas elements: SVG animations using
<animate>or SMIL, and Canvas-based games or data visualizations, are rarely tested with PEAT or frame-rate tools, yet they are fully capable of exceeding the flash threshold. - Relying solely on axe-core or Lighthouse to confirm 2.3.2 compliance: Automated tools cannot detect this criterion. A clean automated scan result means nothing for 2.3.2; only manual review and PEAT analysis can confirm compliance.
- Treating
prefers-reduced-motionas a complete fix for 2.3.2: Respecting theprefers-reduced-motionmedia query is a best practice and helpful for many users, but it is a user-opt-in mechanism. WCAG 2.3.2 requires that content be safe by default, not only when the user has set a system preference. Users who have not configured this setting remain at risk. - Applying flash rate limits only to video but not to CSS, JavaScript, or GIF animations: Teams sometimes audit video content with PEAT but overlook CSS keyframe animations and JavaScript-driven toggles. All animation technologies must be evaluated.
- Using background-image CSS properties to display animated GIFs: Animated GIFs set as CSS background images are less visible to testers doing a visual scan and are easy to overlook during audits. Always include background images in your animation inventory.
- Failing to re-test after A/B testing or personalization changes inject new animated content: Marketing and personalization systems can dynamically inject banners or overlays with animations that were never reviewed for WCAG 2.3.2 compliance. Establish a review gate for any dynamically injected content.
Relation to Turkey's Accessibility Regulations
Turkey's Presidential Circular 2025/10, published in Official Gazette No. 32933 on June 21, 2025, establishes mandatory web and mobile accessibility standards for a broad range of entities operating in Turkey. The circular adopts WCAG 2.2 as its technical reference framework, with mandatory compliance generally required at Level A and Level AA.
WCAG 2.3.2 is a Level AAA criterion and is therefore not legally mandated under the circular for most covered entities. However, its subject matter — the prevention of content that can trigger seizures — intersects directly with the general duty of care and non-discrimination principles that underpin the regulation. The following entity types are covered by the circular and should treat 2.3.2 as a strong best-practice obligation even where it is not strictly required: e-commerce platforms, public institutions and government agencies, banks and financial institutions, hospitals and healthcare providers, telecommunications companies with 200,000 or more subscribers, travel agencies, private transport companies, and private schools authorized by the Ministry of National Education (MoNE).
For public institutions and healthcare providers in particular, the ethical stakes of 2.3.2 are especially high. A government health portal or a hospital patient-information page that triggers a seizure in a photosensitive visitor would represent both a safety failure and a reputational crisis. Although the circular does not explicitly mandate AAA compliance, organizations seeking to demonstrate best-in-class accessibility — whether for procurement eligibility, public trust, or international business partnerships — should implement 2.3.2 alongside their mandatory A and AA obligations.
Organizations that provide services to the European Union market should also note that the European Accessibility Act (EAA), which entered application in June 2025, references EN 301 549, which in turn references WCAG. Turkish companies exporting digital products or services to EU member states may face stricter requirements through that channel. Implementing 2.3.2 proactively positions Turkish organizations well for both domestic and cross-border compliance.
From a practical implementation standpoint, the Accsible overlay widget SDK can assist covered organizations by providing users with the option to pause or stop all animations on a page, which helps reduce photosensitivity risk for users who are aware of their condition. However, this user-triggered control is a supplementary measure, not a substitute for removing or slowing down flashing content at the source, as 2.3.2 requires.
Sources & references
- W3C Understanding 2.3.2 Three Flashes
- W3C Techniques for 2.3.2
- WebAIM: Seizure and Vestibular Disorders
- Trace Center: Photosensitive Epilepsy Analysis Tool (PEAT)
- MDN: prefers-reduced-motion
- MDN: CSS animation-duration
- W3C General Technique G19: Ensuring no component flashes more than three times in any 1-second period
