Projects bibleweb Docs atmosphere-accessibility.md

Accessibility Considerations for Animated Backgrounds and Visual Effects

Last modified March 28, 2026

Accessibility Considerations for Animated Backgrounds and Visual Effects

Project: BibleWeb — Atmospheric Background System Date: 2026-03-29 Context: Pixel art ambient scenes with animated water, campfire flicker, floating particles, and dust effects. Primary audience includes older users (55+, 65+, 75+).


Executive Summary

Animated atmospheric backgrounds introduce real accessibility risk for several overlapping user groups: people with photosensitive epilepsy, vestibular disorders, cognitive disabilities, and age-related visual processing decline. The good news is that ambient, atmospheric motion (slow-moving water, floating dust, gentle particles) sits far from the danger zones if implemented correctly. The primary obligations are: (1) respect prefers-reduced-motion, (2) keep flicker rates below 3 Hz, (3) provide a pause/disable control, and (4) ensure the background never competes visually with foreground content.


1. WCAG 2.3.1 — Three Flashes or Below Threshold (Level A)

Requirement: Web pages must not contain anything that flashes more than three times in any one-second period, OR the flash must fall below the general flash and red flash thresholds.

Exact Thresholds

  • Frequency: No more than 3 flashes per second (3 Hz)
  • Luminance change: A "flash" is a relative luminance change of 10% or more between a light state and dark state
  • Red flash: Saturated red flashing is separately restricted because it is more epileptogenic; special thresholds apply to red content
  • Safe area exception: Content that flashes faster than 3 Hz is permissible only if it occupies less than 25% of a 10-degree visual field — approximately a contiguous area of 341 × 256 pixels (21,824 sq px) at 1024 × 768 viewport size

Applying This to Our Scenes

Effect Risk Level Notes
Campfire flicker Medium If flicker simulates real flame (10–20 Hz), this is a direct WCAG 2.3.1 violation
Animated water shimmer Low Slow oscillation, not a sharp luminance switch
Floating dust/particles Low Individual particles are small; combined area unlikely to exceed threshold
Particle burst events Medium Sudden particle explosions could cross area threshold

Campfire is the critical case. Real campfire flickers at roughly 8–12 Hz. A pixel art campfire that animates at full luminance contrast at that frequency over a large screen area would fail WCAG 2.3.1. The fix is either: (a) cap the flicker frequency to no more than 3 Hz, or (b) ensure the flame occupies less than 341 × 256 pixels of the viewport, or (c) use low-contrast luminance changes (under 10% relative luminance swing) to keep it sub-threshold even at higher frequencies.


2. WCAG 2.3.2 — Three Flashes (Level AAA)

Requirement: Web pages must not contain anything that flashes more than three times in any one-second period — with no safe area exception.

Level AAA removes the area escape hatch entirely. To meet AAA, nothing on the page may flash faster than 3 Hz regardless of size. For a Bible study app aiming to serve older and disabled users well, targeting AAA here is achievable and worth doing — it simply means capping campfire animation at ≤3 Hz.


3. WCAG 2.3.3 — Animation from Interactions (Level AAA)

Requirement: Motion animation triggered by interaction can be disabled, unless the animation is essential to the functionality or information being conveyed.

This criterion covers animations that respond to user input. In our app this includes:

  • Scene transitions when switching Bible books
  • Parallax effects if the background responds to scroll position
  • Any particle burst triggered by tapping/clicking a verse

The preferred implementation is to honour prefers-reduced-motion and disable or replace these triggered animations. A second acceptable approach is an in-app toggle. Background animations that play continuously (ambient loops) are addressed more by WCAG 2.2.2 and 2.3.1 than by 2.3.3, but the prefers-reduced-motion response should cover all of them together.


4. WCAG 2.2.2 — Pause, Stop, Hide (Level A)

Requirement: For any moving or blinking content that starts automatically, lasts more than 5 seconds, and is presented alongside other content, the user must have a mechanism to pause, stop, or hide it.

Our atmospheric backgrounds are continuous ambient loops that run for the entire session — clearly beyond 5 seconds. This means WCAG 2.2.2 compliance is mandatory, not optional:

  • Provide a visible pause/disable button for the background animation
  • Or honour prefers-reduced-motion to automatically stop it (this alone satisfies the intent, though a visible control is more discoverable)

The control must not trap keyboard focus or interfere with page usability. A small, accessible icon button in the corner of the scene is sufficient.


5. prefers-reduced-motion

What It Does

prefers-reduced-motion is a CSS Level 5 media feature that reflects the user's OS-level preference to reduce motion. It is set in:

  • macOS: System Preferences → Accessibility → Reduce Motion
  • Windows: Settings → Ease of Access → Display → Show animations
  • iOS/Android: equivalent accessibility settings

CSS Implementation

/* Default: animations play */
.scene-canvas {
  animation: float 4s ease-in-out infinite;
}

/* Reduced motion: stop all non-essential animation */
@media (prefers-reduced-motion: reduce) {
  .scene-canvas,
  .particle,
  .campfire-sprite,
  .water-shimmer {
    animation: none;
    transition: none;
  }
}

The recommended pattern for our pixel art scenes is progressive enhancement: define the static version as the base, then add animation for users who have not expressed a preference:

/* Base: static scene, no motion */
.campfire { /* static sprite frame */ }

/* Enhancement: animate if no preference */
@media (prefers-reduced-motion: no-preference) {
  .campfire { animation: flicker 0.3s steps(3) infinite; }
}

JavaScript Detection for Canvas Animations

Since our pixel art scenes render in Canvas or via requestAnimationFrame, CSS alone will not stop them. JS detection is essential:

// Detect preference
const prefersReducedMotion = window.matchMedia(
  '(prefers-reduced-motion: reduce)'
).matches;

// React to changes at runtime (user changes OS setting while page is open)
const motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
motionQuery.addEventListener('change', (e) => {
  if (e.matches) {
    stopAllSceneAnimations();
    renderStaticSceneFrame();
  } else {
    startSceneAnimationLoop();
  }
});

SvelteKit / Svelte 5 Pattern

// lib/stores/motion.svelte.ts
import { readable } from 'svelte/store';

export const reducedMotion = readable(false, (set) => {
  if (typeof window === 'undefined') return;
  const query = window.matchMedia('(prefers-reduced-motion: reduce)');
  set(query.matches);
  const handler = (e: MediaQueryListEvent) => set(e.matches);
  query.addEventListener('change', handler);
  return () => query.removeEventListener('change', handler);
});

Then in any scene component, bind animation start/stop to this store.

What to Do When Reduced Motion Is Active

Do not simply kill everything — that can strip meaningful feedback. Instead:

Animation Type Reduced Motion Behaviour
Ambient background loop (water, dust, wind) Stop entirely; show single static frame
Campfire flicker Replace with static warm glow (orange tinted static frame)
Scene transition (fade in/out) Keep opacity fade; remove scale/translate
Particle burst on verse tap Replace with instant appearance; no physics
Loading spinner Replace with static icon + "Loading…" text

6. prefers-contrast and Forced Colors

prefers-contrast

Values: more, less, custom, no-preference. Most relevant is more, triggered by macOS "Increase Contrast" or when forced-colors is active with a high foreground/background ratio (≥7:1).

For our animated backgrounds: high contrast mode users need text to remain readable against whatever background is shown. The background scenes should never interfere with text legibility. Recommended approach: when prefers-contrast: more is active, significantly darken and desaturate the background or replace it with a solid near-black, and ensure all overlaid text uses a system-color-compatible class.

forced-colors

In Windows High Contrast mode (forced-colors: active), the browser overrides CSS color properties with system colors. Standard CSS backgrounds and borders are affected, but Canvas and WebGL content is not automatically overridden — it continues to render in the colors your JavaScript draws.

This means:

  • If your scene is a <canvas> element, forced-colors mode will not apply a high-contrast palette to it
  • Users in High Contrast mode will see the pixel art scene as-is, potentially defeating the purpose of High Contrast mode
  • Text overlaid on canvas must maintain sufficient contrast manually
@media (forced-colors: active) {
  .scene-canvas {
    /* Hide or heavily dim the canvas so it doesn't fight system colors */
    opacity: 0.15;
  }

  .scene-overlay {
    background: Canvas;
    color: CanvasText;
  }
}

Consider providing a completely non-canvas fallback (a solid background using system colors) when forced-colors: active.


7. Vestibular Disorders

Who Is Affected

As many as 35% of adults aged 40+ in the United States have experienced some form of vestibular dysfunction. Vestibular disorders affect the inner ear and disrupt the brain's interpretation of motion and spatial orientation. Visual motion on screen can trigger: vertigo, nausea, migraines, disorientation, vomiting.

Triggering Motion Patterns

The highest-risk patterns for vestibular users are:

  1. Large-area motion — background objects moving across significant screen space
  2. Parallax — foreground and background moving at different speeds/directions when scrolling
  3. Sudden movement — content that snaps or jumps unexpectedly
  4. Optical flow — full-screen movement that makes the user feel like they are moving

Our App's Risk Profile

Our ambient backgrounds involve slow, continuous motion in a fixed background layer with no parallax (Bible study content scrolls in the foreground). This is a lower-risk profile. The key safeguards are:

  • Keep motion speed slow and predictable (gentle float, not rapid drift)
  • Avoid background elements reacting to scroll position (no parallax)
  • Avoid sudden particle bursts triggered by scroll events
  • Confine motion to clearly decorative background elements; foreground content is fully static

8. Photosensitive Epilepsy

Thresholds

Photosensitive epilepsy can be triggered by:

  • Flashing at 3 Hz or higher (3 times per second or faster)
  • Luminance at least 20 cd/m²
  • Occupying a solid visual angle of at least 0.006 steradians (roughly 21,824 sq px at typical viewing distance)

The most dangerous frequencies are 15–25 Hz (centre of the hazard range). Below 3 Hz is generally considered safe. Red flashing is more epileptogenic than other colours.

Our Campfire Risk

A pixel art campfire with a looping 3-frame animation cycling at ~10 fps = ~3.3 Hz. This is in the danger zone. Safe implementation:

  • Option A: Animate the fire at 2 fps or less (one cycle every 0.5 seconds). This looks slow but is visually acceptable for a cosy ambient effect.
  • Option B: Use a 3-frame loop at any speed but with luminance delta under 10% between frames (dark-to-dark palette, no bright yellow/white flash).
  • Option C: Combine both — slow cycle rate + low luminance contrast. This is the safest and easiest to achieve aesthetically with warm amber/orange tones.

Testing Tool: PEAT

The Photosensitive Epilepsy Analysis Tool (PEAT) from the TRACE Center at University of Maryland is the standard free tool:

  • URL: https://trace.umd.edu/peat/
  • Windows only, desktop application
  • Analyses screen recordings of your animation for flash frequency and area violations
  • Reports general flash failures, red flash failures, and extended flash warnings

For Canvas animations, record a screen capture of the scene and run it through PEAT before shipping.


9. Older Users and Animation (55+, 65+, 75+)

Age-Related Changes Relevant to Animation

Change Impact on Animation
Reduced contrast sensitivity Low-contrast ambient effects may be invisible or straining
Slower visual processing Fast animations cause confusion; user can't track what happened
Reduced ability to filter visual noise Animated backgrounds compete more strongly with foreground text
Increased motion sensitivity Older adults more susceptible to vestibular responses from motion
Cognitive load increases Working memory is taxed; any background distraction has higher cost
Higher rates of photosensitivity Epilepsy and seizure disorders increase in prevalence with age

Research-Based Design Principles for Older Users

Recent age-friendly animation research (2024–2025) identified these preferences for elderly users:

  • Short duration — animations complete quickly or loop slowly
  • Simplified information — no complex multi-element motion
  • Visual clarity — high contrast, clear shapes
  • Visual stability — backgrounds should feel anchored, not drifting
  • Controlled pacing — user controls when motion occurs (not constant autoplay)
  • Soft and neutral colors — avoid saturated, high-chroma motion

Practical Impact for BibleWeb

The 55+ Bible study audience is precisely the population where: (a) vestibular dysfunction is common, (b) visual processing is slower, (c) background distraction has higher cognitive cost, and (d) the likelihood of photosensitive conditions is elevated. The atmospheric background must be:

  • Subtle enough to fade from conscious attention during reading
  • Slow enough that it never demands visual tracking
  • Pausable via a clearly visible control (large enough for reduced motor precision)
  • Off by default for the oldest age groups, or provided with a first-run accessibility prompt

10. Cognitive Load and ADHD

Background Animation and Reading

Unnecessary animations, auto-play media, and environmental motion increase extraneous cognitive load — cognitive effort spent processing irrelevant information that competes with the primary task (reading scripture, studying notes).

Key findings from cognitive load research:

  • ADHD users experience greater difficulty filtering out background visual information
  • Animated backgrounds are a known distractor that degrades reading comprehension in cognitively loaded situations
  • Users with ADHD already experience reduced working memory; any additional load compresses capacity for actual content

Design Recommendations

  • The background must read as "wallpaper" — so undemanding that the eye quickly learns to ignore it
  • Use extremely slow, repetitive motion patterns (the brain habituates to predictable motion and stops allocating attention to it)
  • Avoid sudden changes in the background that re-capture attention (no triggered events, no state changes that cause visible scene shifts during reading)
  • The background should be noticeably darker/dimmer than content by default
  • Consider a "Focus Mode" that flattens the background to a solid color — directly serving ADHD and cognitive accessibility users

11. Legal Requirements

United States

ADA Title III (public accommodations) and ADA Title II (state/local government) both require equal access for people with disabilities. Courts have consistently ruled that websites and apps are "places of public accommodation" under Title III. The DOJ finalized ADA Title II web rules in April 2024, explicitly requiring WCAG 2.1 Level AA compliance for government websites by April 2026.

Section 508 governs federal government digital content. It references WCAG 2.1 Level AA as the technical standard. For a commercial SaaS app like BibleWeb, Section 508 is not directly applicable but sets the industry benchmark.

Europe

EN 301 549 v3.2.1 (2021) is the harmonised European standard for ICT accessibility. It incorporates WCAG 2.1 in full. The European Accessibility Act (EAA) mandates compliance with EN 301 549 for digital products and services sold in the EU, with enforcement beginning June 2025. The next version (v4.1.1, expected 2026) will include WCAG 2.2 AA.

Animation-specific legal exposure maps directly to WCAG criteria: a WCAG 2.3.1 failure (flashing content triggering a seizure) is the most actionable litigation vector. There are documented cases of users filing complaints and lawsuits over content that triggered seizures or caused physical harm.

Bottom Line for BibleWeb

WCAG 2.1 Level AA compliance is the legally defensible floor. For animations this means:

  • 2.2.2 Pause/Stop/Hide: Level A — mandatory
  • 2.3.1 Three Flashes or Below Threshold: Level A — mandatory
  • 2.3.3 Animation from Interactions: Level AAA — recommended (achievable at low cost)

12. Graceful Degradation Strategies

Hierarchy of Fallbacks

When animations are disabled (via prefers-reduced-motion or user toggle), show the most visually appealing static version, not a blank canvas:

  1. Static scene render — a single representative frame of the pixel art scene. The campfire is a warm ember glow. The water is a flat lake. The night sky has stars but no movement. This preserves the atmosphere without any motion.

  2. Blurred/faded scene — if the static frame looks too stark, apply a slight CSS blur (filter: blur(1px)) and reduced opacity (opacity: 0.6) to soften it into a background texture without looking broken.

  3. Solid color with gradient — if the user is in forced-colors mode or very high contrast mode, fall back to a solid dark background using system Canvas color. No scene at all.

SvelteKit Implementation Pattern

<!-- SceneBackground.svelte -->
<script lang="ts">
  import { reducedMotion } from '$lib/stores/motion.svelte';
  import { onMount } from 'svelte';

  let canvas: HTMLCanvasElement;
  let animating = $state(false);

  onMount(() => {
    // Render single static frame immediately
    renderStaticFrame(canvas);

    // Only start animation loop if motion is acceptable
    if (!$reducedMotion) {
      animating = true;
      startAnimationLoop(canvas);
    }

    // React to runtime changes
    return reducedMotion.subscribe((reduced) => {
      if (reduced && animating) {
        animating = false;
        stopAnimationLoop();
        renderStaticFrame(canvas); // Freeze on a clean frame
      } else if (!reduced && !animating) {
        animating = true;
        startAnimationLoop(canvas);
      }
    });
  });
</script>

<canvas
  bind:this={canvas}
  class="scene-bg"
  aria-hidden="true"
  role="presentation"
/>

ARIA Considerations

The background canvas should always have aria-hidden="true" — it is purely decorative and screen readers must not announce it. Role presentation or none reinforces this.

User-Facing Control

Per WCAG 2.2.2, provide a visible in-app control:

<button
  aria-label="Pause background animation"
  aria-pressed={!animating}
  class="scene-toggle"
  onclick={toggleAnimation}
>
  {animating ? '⏸' : '▶'}
</button>

The button must be keyboard-accessible, have a visible focus indicator, and be large enough for touch users (minimum 44 × 44 CSS px per WCAG 2.5.5).


13. Testing Tools and Methodology

Tool Purpose Platform
PEAT (trace.umd.edu/peat) Flash frequency and area analysis of screen recordings Windows desktop
Harding FPA Professional broadcast-grade photosensitivity analysis Licensed
axe DevTools General WCAG automated audit Browser extension
WAVE (wave.webaim.org) General WCAG audit including some motion flags Browser extension
Browser DevTools Toggle prefers-reduced-motion in Rendering panel (Chrome/Firefox) Built-in
Lighthouse General accessibility audit Built-in Chrome DevTools

Testing Procedure for Atmospheric Scenes

  1. Build the scene with all animations running
  2. Screen record a 10-second clip of each scene (campfire, water, particles)
  3. Run PEAT on each recording — fix any general flash or red flash failures
  4. Test in Chrome DevTools with prefers-reduced-motion: reduce emulated — confirm Canvas stops, static frame renders
  5. Test in Windows High Contrast mode (or emulate with forced-colors: active) — confirm text remains readable, canvas is suppressed
  6. Manual review: watch each scene for 30 seconds focusing on the text content — if the background ever re-captures attention, the motion is too prominent
  7. User test with 55+ users specifically — observe whether they notice the background and whether it causes discomfort

Summary of Implementation Requirements

Requirement Standard Priority Action
Cap campfire flicker to ≤3 Hz WCAG 2.3.1 (A) Critical Limit animation frame rate
Provide pause/stop control WCAG 2.2.2 (A) Critical Add visible toggle button
Honour prefers-reduced-motion WCAG 2.3.3 (AAA) High JS matchMedia + stop Canvas loop
Static scene fallback WCAG 2.2.2 + best practice High Freeze on single clean frame
Suppress Canvas in forced-colors Best practice Medium CSS opacity rule
Dim background vs. foreground text Cognitive/WCAG 1.4.3 High Background opacity ≤0.6
aria-hidden on canvas WCAG 1.3.1 (A) High Already: decorative element
Focus Mode (solid background) Cognitive accessibility Medium User-toggled setting
Run PEAT before shipping QA process High Record + analyse each scene

Sources