data-animate-image

Play/pause control for animated images. Add data-animate-image to any GIF, WebP, or APNG for a toggle button with automatic reduced-motion support.

Overview

The data-animate-image attribute adds a play/pause toggle button to animated images. Users can stop distracting animations with a single click, and the image automatically pauses when prefers-reduced-motion is active.

<img src="animation.gif" data-animate-image alt="Animated demo">

How It Works

  1. The init script wraps the <img> in a .animate-image-wrapper container for positioning
  2. A toggle <button> is injected alongside the image
  3. On load, the first frame is captured to a canvas and converted to a static PNG data URL
  4. When paused, the image src is swapped to the static frame; when played, it reverts to the original animated source
  5. The data-animate-image-paused attribute tracks the paused state
<!-- Before enhancement --> <img src="animation.gif" data-animate-image alt="Demo"> <!-- After enhancement (auto-generated wrapper) --> <div class="animate-image-wrapper"> <img src="animation.gif" data-animate-image data-animate-image-init alt="Demo"> <button type="button" class="animate-image-toggle" aria-label="Pause animation"></button> </div>

Attributes

Attribute Type Description
data-animate-image boolean Marks an <img> for animation control enhancement.
data-animate-image-paused boolean Set initially to start the image paused. Also set/removed automatically when the user toggles playback.
data-animate-image-init boolean Set automatically to prevent double-binding. Do not set manually.

Start Paused

Add data-animate-image-paused to the image to start it in a paused state. The first frame is captured on load and displayed as a static image until the user clicks play.

<img src="animation.gif" data-animate-image data-animate-image-paused alt="Paused by default">

Reduced Motion

The init script automatically pauses animated images when the user has requested reduced motion. This is detected via two mechanisms:

  • prefers-reduced-motion: reduce — the OS-level media query
  • data-motion-reduced attribute on <html> — for app-level motion controls

When either is active, images are auto-paused after the first frame is captured. The user can still manually play the animation using the toggle button.

Runtime changes to the prefers-reduced-motion media query are also detected — if the user enables reduced motion while viewing the page, animated images will pause automatically.

/* The init script checks for reduced motion preference: * * 1. prefers-reduced-motion: reduce (OS setting) * 2. data-motion-reduced attribute on <html> * * If either is true, the image is auto-paused after * the first frame is captured. The user can still * click the play button to resume manually. */

Dynamic Elements

Images added to the DOM after page load are automatically enhanced via a MutationObserver. No manual initialization is needed.

// Dynamically added images are auto-enhanced via MutationObserver const img = document.createElement('img'); img.src = 'animation.gif'; img.alt = 'Dynamic animation'; img.dataset.animateImage = ''; document.body.appendChild(img); // img is wrapped and enhanced automatically — no manual init needed

Accessibility

  • The toggle button has an aria-label that updates to "Pause animation" or "Play animation" based on state
  • Respects prefers-reduced-motion: reduce by auto-pausing — users who find motion distracting see a static image by default
  • Also respects a page-level data-motion-reduced attribute on <html>
  • The toggle button is keyboard-accessible (focusable, activated with Enter/Space)
  • Without JavaScript, the image displays normally — progressive enhancement ensures the animated content is never lost
  • Falls back gracefully for cross-origin images where canvas capture may be blocked by CORS