Stop Autoplaying GIFs with prefers-reduced-motion
The prefers-reduced-motion CSS media query is an
accessibility feature that detects if a user has requested their
operating system to minimize non-essential movement. Because standard
animated GIF files loop indefinitely and lack native playback controls,
developers cannot simply pause them using a single CSS property.
Instead, developers utilize the prefers-reduced-motion
media query in conjunction with HTML elements or CSS background swaps to
replace autoplaying GIFs with static images, effectively suppressing
unwanted animation for motion-sensitive users.
The Problem with Animated GIFs
Animated GIFs lack native pause, stop, or play controls. Once
rendered in a browser, they loop continuously. For users with vestibular
disorders, motion sensitivities, or cognitive distractions, this
continuous motion can cause dizziness, nausea, headaches, or loss of
focus. Because CSS cannot directly manipulate the internal frame
playback of an encoded .gif file, developers must intercept
the asset delivery to ensure motion is suppressed.
Detecting the Motion Preference
Operating systems like Windows, macOS, iOS, and Android allow users to enable a "Reduce Motion" setting. Browsers expose this operating system setting to web applications through the CSS media query:
@media (prefers-reduced-motion: reduce) {
/* Motion-suppressing styles applied here */
}The media query accepts two primary values:
no-preference: The user has not requested reduced motion; default animations and autoplay behaviors can proceed.reduce: The user has explicitly enabled settings to minimize animations, transitions, and automatic movement.
Suppressing
GIFs Using the HTML <picture> Element
The most efficient way to suppress an autoplaying GIF is by using the
HTML <picture> element. This approach allows the
browser to evaluate the media query before downloading the image,
preventing unnecessary bandwidth usage.
<picture>
<source srcset="static-frame.png" media="(prefers-reduced-motion: reduce)">
<img src="animated-graphic.gif" alt="Description of the animated demonstration">
</picture>In this implementation, if the user’s system is set to reduced
motion, the browser loads static-frame.png (a still capture
of the first or most representative frame of the GIF). If no motion
preference is set, the browser downloads and displays
animated-graphic.gif.
Suppressing GIFs Using CSS Background Swaps
When GIFs are used as decorative visual elements via CSS background
properties, developers can suppress them by overriding the
background-image property directly within a media query
block.
.hero-banner {
background-image: url('animated-background.gif');
}
@media (prefers-reduced-motion: reduce) {
.hero-banner {
background-image: url('static-background.png');
}
}When reduce is active, the browser overrides the
animated asset with the static file, stopping all background motion
automatically.
Suppressing GIFs Through Class Toggling with JavaScript
In cases where interactive components require manual control,
developers can read the media query via JavaScript using
window.matchMedia() and conditionally swap the image source
attribute.
const motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
const animatedImage = document.querySelector('.dynamic-gif');
function handleMotionPreference(e) {
if (e.matches) {
animatedImage.src = 'static-frame.png';
} else {
animatedImage.src = 'animated-graphic.gif';
}
}
// Initial check and event listener for real-time changes
handleMotionPreference(motionQuery);
motionQuery.addEventListener('change', handleMotionPreference);This approach dynamically updates the image source if a user toggles their system settings while browsing the page.
Modern Alternative: Replacing GIFs with HTML5 Video
Because GIFs are inefficient in file size and difficult to control
programmatically, many developers replace them with looping HTML5 video
files (.mp4 or .webm). Unlike GIFs, HTML5
video provides native JavaScript controls:
<video id="looping-media" autoplay loop muted playsinline>
<source src="animation.mp4" type="video/mp4">
</video>const motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
const video = document.getElementById('looping-media');
if (motionQuery.matches) {
video.pause();
video.removeAttribute('autoplay');
}Converting GIFs to video files combined with
prefers-reduced-motion gives developers complete control
over stopping and starting animations, drastically improves page load
performance, and guarantees a safe browsing experience for all
users.