Accessibility · Perception

Computing the Flash Threshold: Luminance Steps, Area, and the Red Flash Rule

Photosensitive seizures depend on the size, luminance delta, and frequency of a flashing region; how the general and red flash thresholds are defined, and why a small bright animation is a different risk from a full-screen one.

A flashing region can induce a seizure in a photosensitive viewer, and the risk is not a simple function of brightness. It depends on three interacting quantities: how large the flashing area subtends in the visual field, how big the luminance step is on each transition, and how often the transitions occur. A small animation that blinks at high contrast is usually harmless because it occupies too little of the retina; a full-screen flash at a modest contrast can be dangerous because it occupies most of it. The thresholds that encode this are computable, and the computation has a specific structure that makes some failure modes obvious and others invisible.

Defining a flash in terms of luminance

The standard definition treats a flash as a pair of opposing changes in relative luminance, each of which is at least 10 percent of the maximum luminance, with the darker of the two below 0.80. “Opposing” means the direction reverses: bright to dark, then dark to bright. A single transition from bright to dark is not a flash; a sequence of transitions in the same direction is not a flash either, though it can still be uncomfortable.

The two numerical clauses do different work. The 10 percent floor excludes slow fades and low-contrast pulsing, which do not drive the response. The 0.80 ceiling excludes sequences that stay in the bright end of the range: a transition between 0.85 and 0.95 meets the 10 percent floor but is excluded because neither side is below 0.80, and the absolute change in retinal illumination at that level is small relative to the eye’s adaptation state. A transition between 0.05 and 0.15 also meets the floor and is included, because it sits at the dark end where the same absolute change is a much larger fraction of the local signal.

The definition uses relative luminance, not lightness, not channel values. A red-to-green alternation at constant luminance is not a flash under this definition even though it may be visually jarring, because the luminance step is zero. Conversely, an alternation between two colors of the same hue but different luminance is a flash. This is one of the few places where the luminance-only model is the correct model rather than an approximation, because the physiological response is driven by luminance change in the magnocellular pathway rather than by chromatic change.

Area: the 25 percent rule and the pixel rectangle

The general flash threshold applies when the flashing region occupies more than 25 percent of a 10-degree visual field, and the standard operationalises this as a rectangle of 341 by 256 pixels at a viewing resolution of 1024 by 768. The numbers are not arbitrary: they correspond to about 10 degrees of visual angle at a typical viewing distance for that resolution, and the 25 percent is the fraction of that field above which the response becomes likely rather than marginal.

Two consequences follow, and they pull in opposite directions.

The first is that the threshold is a fraction of a fixed field, not a fraction of the screen. A flashing element that covers a quarter of a small viewport covers more than a quarter of the 341×256 rectangle and is over the limit; the same element on a large monitor covers a smaller fraction of the visual field and may be under it. The safe assumption is the small viewport, since that is the worse case.

The second is that the rectangle is an approximation of an area, and the practical rule is to compute the union of the flashing regions rather than the bounding box of everything that changes. A page where four small elements flash in different corners has four small flashing regions, each of which may be under the threshold; a page where a full-width band flashes has one large region. A checker that computes the bounding box of all changed pixels will over-report the first case and a checker that computes per-element areas will under-report a case where the elements are adjacent and effectively contiguous. The correct treatment is the union of connected regions, which is why this measurement is done on rendered frames rather than on markup, and why an audit that reads computed styles cannot answer the question.

Frequency and the three-per-second limit

The general threshold permits at most three flashes in any one-second period. The window matters: the rule is not an average rate but a maximum in any sliding one-second window, so four flashes spread evenly over 1.2 seconds violates it even though the average is under 3.3 per second. Checking requires a sliding window over the transition timestamps, not a count divided by duration.

There is a compensating clause for small areas. A flash sequence that exceeds three per second is permitted if the flashing area is below one quarter of the 341×256 rectangle — that is, below about 21,824 square pixels at the reference resolution, which is a square of roughly 148 pixels on a side. The clause exists because the empirical work behind the thresholds found that small regions do not provoke the response even at high rates. It is the reason a small blinking cursor or a spinner is not a violation.

The clause is a trap in composition. Two small elements that each sit just under the area limit, flashing in phase and adjacent to each other, form one region that is over it. Whether they are “adjacent” is a rendering question, not a markup question: a 4 px gap between two 140 px squares reads as one flashing area to the eye. This is the same connectedness problem as above, and it is the failure that a per-element audit cannot see.

The saturated red clause

Red flashes are treated separately because the response to them is stronger. A transition that involves a saturated red — a red whose contribution to luminance dominates its other channels in a specific sense, roughly a deeply saturated red with low green and blue — is evaluated against a stricter pair of thresholds, and the area and frequency limits that apply to it are tighter than the general case.

The operational definition of saturated red in the standard is a condition on the proportions of the channels rather than on absolute brightness: a red whose share of the total channel sum is very high, so that it is close to the red corner of the gamut. A desaturated pink fails that test because its green and blue contributions are large. A dark red such as a deep maroon passes it, because its green and blue are still near zero, and the stricter rule then applies to it as well. What the rule does not do is exempt a red because it is dim: dimness affects whether the luminance step is large enough to count as a flash at all, and that is the separate 10 percent clause.

The practical implication is that a red-alternating animation can fail the threshold at a smaller area than the general rule permits, and that the failure depends on the exact colors rather than on the luminance delta alone. This is the one part of the computation where a hue-aware analysis is required, because a luminance-only check will pass a red flash that the stricter rule rejects.

def within_flash_limit(times, window=1.0, max_flashes=3):
    """times: sorted transition instants in seconds for one connected region."""
    for t0 in times:
        # the rule is a sliding one-second window, not an average over the clip
        if sum(1 for t in times if t0 <= t < t0 + window) > max_flashes:
            return False
    return True

Why video is the hard case

Everything above is straightforward for a CSS animation with a known keyframe timeline. Video is not, because the luminance changes are embedded in compressed frames, and the encoder’s own decisions affect the measurement. A scene that appears to flash steadily in the source can produce a different transition pattern after compression, and a compression artifact can introduce a luminance step that was not in the source.

The measurement that matters is therefore over decoded frames at the display rate, with the region masks computed per frame. The reference resolution for the area calculation is a convention that lets a producer reason about a file before it is displayed; the actual risk depends on the display size, which the producer does not control. This is why the guidance for broadcast material specifies a reference viewing condition — a screen of a given diagonal at a given distance — and why a file that passes at that condition can still be risky on a larger display closer to the viewer.

Content that is not full-screen has the same ambiguity. A flashing advertisement embedded in a page occupies a small fraction of the screen and a large fraction of the 341×256 rectangle when the page is scrolled so that the advertisement fills the field. The area rule is expressed in terms of visual field rather than screen, so the honest analysis has to consider the case where the element is large in the field of view, which is the case the user can create by scrolling and zooming.

The mitigation set is small and mostly structural: cap the number of transitions, reduce the luminance delta below 10 percent, keep the flashing area under the small-area limit, or gate the content behind an explicit play action so that it does not begin unannounced. The last option is the one that survives contact with content whose flash pattern cannot be edited, and it is the same principle as gating motion behind a user action in the reduced-motion work: the user gets to decide whether to start it.

References

  1. Web Content Accessibility Guidelines (WCAG) 2.2 — Three Flashes or Below Threshold — W3C WAI
  2. Web Content Accessibility Guidelines (WCAG) 2.2 — W3C
  3. ITU-R BT.1702: Guidance for the reduction of photosensitive epileptic seizures caused by television — ITU-R
  4. Ofcom Guidance: Guidelines for Flashing Images and Regular Patterns in Television — Ofcom