Title: CSS Image Animation Module Level 1
Shortname: css-image-animation
Level: 1
group: csswg
Status: ED
Prepare for TR: no
Work Status: exploring
ED: https://drafts.csswg.org/css-image-animation-1/
TR: https://www.w3.org/TR/css-image-animation-1/
Previous Version: https://webplatform.design/projects/image-animation/image-animation-property/spec/overview
Editor: Florian Rivoal, http://florian.rivoal.net, w3cid 43241
Complain About: accidental-2119 yes, missing-example-ids yes
Infer CSS Dfns: yes
Markup Shorthands: markdown yes, css yes
Abstract: This CSS module proposes facilities to control the rendering of animated images.
spec:html; type:element; text:body
{
"IMAGE-ANIMATION-EXPLAINER": {
"authors": [
"Florian Rivoal",
"Lea Verou"
],
"href": "https://drafts.csswg.org/css-image-animation-1/explainer",
"title": "CSS Image Animation Explainer"
},
"IMAGE-ANIMATION-TALK": {
"authors": [
"Lea Verou",
"Florian Rivoal"
],
"href": "https://github.com/webplatformco/project-image-animation/tree/main/image-animation-property",
"title": "We need to be able to control Image Animation on the Web Platform!"
}
}
Introduction {#intro}
=====================
This section is non-normative.
Animated images (as enabled by [[GIF]], [[PNG]], [[WebP]]…) are in common use on the web.
By default, user agents autoplay these images,
which can be jarring for users,
especially in use cases where there are multiple images on a single page (e.g. image galleries),
and violates [[WCAG22#pause-stop-hide]].
Currently,
site authors have no control over this.
This leads to a user desire to control such animations.
However, due to the diversity of usage,
there is a wide range of use cases and desired
UIs and user experiences,
so making this an automatic or opt-in user agent feature [[IMAGE-ANIMATION-EXPLAINER#provide-this-as-a-ua-setting|would not be sufficient]].
To offer their users the best experience,
websites need to control the playback experience,
separately for each different uses of animated images.
This specification proposes a CSS property ('image-animation')
and a pseudo-class ('':animated-image'')
to enable authors to control animations,
and to target this control and any
UI they wish to associate with it
to relevant elements.
For further exploration of the motivations and of the alternatives considered,
see also the separately maintained
[[IMAGE-ANIMATION-EXPLAINER inline|explainer]]
and [[IMAGE-ANIMATION-TALK inline|presentation]]
on this topic.
Nothing in this specification precludes user agents offering users
a setting to control image animation globally,
such as an option to turn all [=animated images=] into [=static images=].
Controlling Image Animations: the 'image-animation' property {#image-animation}
===============================================================================
Name: image-animation
Value: normal | paused | stopped | running
Initial: normal
Applies to: [=content images=] and elements with [=decorative images=]
Inherited: yes
Computed Value: as specified
Animation Type: discrete
This property allows authors to control
whether [=animated images=] are displayed in their animated state
or paused.
Both [=content images=] and [=decorative images=] are affected by this property.
When an element contains several [=decorative images=]
(e.g. multiple background images or border images),
or if it contains both a [=content image=] and one or more [=decorative images=],
the [=computed value=] of the property on that element affects them all.
Note: It is therefore not possible to pause [=decorative images=] of an element
while letting the animation run on the [=content image=] of the same element,
nor vice-versa.
In the case of non-animated images,
the different values of this property have no effect.
This property does not affect [=videos=] nor [=programmatic images=] either.
When this property is applied to the [=root element=],
its effects on background [=decorative images=] are propagated to the [=canvas background=].
Note: For legacy reasons,
the 'background' property propagates not only from the [=root element=],
but also from the HTML <{body}> element.
However, newer properties like 'image-animation' only propagate from the [=root element=].
Setting it on the <{body}> will not propagate,
even if that is where the 'background' is set.
- normal
-
The animation of [=animated images=] is run normally,
as determined by the image format and the host language.
Further,
all [=animated images=] with the same absolute URL,
the same image data,
and with an 'image-animation' computed value of ''normal'''
must be rendered synchronized to the same timeline as a group,
with the timeline starting at the time of the least recent addition to the group.
Note: The above requirement is based on a [[HTML]] rendering expectation defined in [[HTML/rendering#images-3]].
As [[HTML]] does not generally require user agents to present documents in any particular way,
and therefore does not normatively require the above behavior.
This specification does.
- stopped
-
[=Animated images=] are rendered as if they were [=static images=]:
the user agent must not run any animation it contains.
If the image contains a [=cover frame=],
that is what the user agent must use;
otherwise, it must display the image
as it would be in the initial state of the animation.
- paused
-
The user agent must not run the animation
contained in the [=Animated images=],
and must continue to display the image
as it was when this value started to apply,
effectively pausing the animation.
If the animation had not been playing
prior to this value being applied,
the behavior is the same as ''stopped''.
- running
-
Like ''normal'',
the animation of [=animated images=] is run normally,
as determined by the image format and the host language.
However,
animation timelines are scoped per element:
among the [=content image=] and [=decorative images=] of a single element,
any [=animated images=] with the same absolute URL,
the same image data,
and with an 'image-animation' computed value of ''running''
must be rendered synchronized to the same timeline as a group,
distinct from the timeline of images in other elements.
If images are added to the element while the computed value is ''running'',
the timeline starts at the time of the least recent addition to the group.
If the element is created or made visible after having previously been set to ''display: none'',
with images already added and with 'image-animation' already set to ''running'',
the timeline starts when the element is included in the layout.
If this property is switched to ''running'' from another value,
the beginnig of this timeline is set
so that the animation continues from the state that was displayed
at the timem of the switch.
An author can use this property to suppress non-essential image animations
in response to user preferences expressed by the '@media/prefers-reduced-motion' media feature.
Here, [=decorative images=] are made [=static images|static=],
while <{img}> elements are kept animating.
:root { /* propagates through the document by inheritance */
image-animation: paused;
}
img {
image-animation: normal;
}
A given HTML page contains several <{img}> elements
displaying instances of the same image
(same absolute URL and same image data),
all styled with ''image-animation: normal''.
One of the elements has its 'image-animation' property temporarily switched to ''paused'',
stopping the animation of its image.
Other images are unaffected,
and their animation continues.
The 'image-animation' property of the ''paused'' element
is later changed to ''running''.
At that point, that image resumes its animation,
without regard to how far along their timeline other images are,
and is now out of sync.
Later still, the 'image-animation' property of that element
is changed to ''normal''.
At that point, the image's animation snaps back to being synchronized
with the other instances.
The 'image-animation' property affects not only raster image formats,
but also to vector images,
including SVG (see [[SVG2]]).
However, this is only the case for distinct SVG resources loaded as [=content images=] or [=decorative images=],
and does not include <{svg}> elements inlined into HTML documents.
(However, if set on the <{svg}> element,
it does inherit,
and does affect any [=animated image|animated=] [=content image=]
loaded via the SVG <{image}> element.)
Telling Animated Images Apart: the '':animated-image'' pseudo-class {#animated-image-pseudo}
==============================================================================
The :animated-image pseudo-class represents [=content image=] elements
where a [=animated image=] has been loaded.
For the ''animated-image'' pseudo-class to match,
the image must not only be in a format that is capable of animation,
but must also be an actually animated image.
On elements which do not represent [=content images=],
the ''animated-image'' pseudo-class never matches.
This pseudo class can be used for authors
to selectively provide some user interface
to enable users to play paused images.
In this simplistic example,
images that can animate are initially paused,
and a filter is applied to them
to make them look dull and grayed out.
Upon hovering or focusing the image,
the filter is removed
and the image is allowed to play.
img:animated-image {
image-animation: paused;
filter: grayscale(10%) contrast(50%) brightness(80%);
}
img:animated-image:hover,
img:animated-image:focus {
filter: none;
image-animation: running;
}
It is important for authors building
UI
to control the animation of images
to take the needs of keyboard users into consideration,
and to avoid making the interaction rely solely on mouse interactions.
In the
above example,
play is triggered not only by hovering the image
but also by focusing it.
To make this fully functional,
it would be necessary to make animatable images focusable.
This could be accomplished with something
like the following code snippet.
function setImageFocusability(event) {
var img = event.target;
if (img.matches(":animated-image") {
img.tabIndex = 0;
} else {
img.removeAttribute("tabindex");
}
}
document.querySelectorAll("img").forEach( (i) => {
setImageFocusability({target: i });
i.addEventListener('load', setImageFocusability);
i.addEventListener('error', setImageFocusability);
});
Whether '':animated-image'' matches is not affected
by the current playing state of the image,
nor by the value of the ''image-animation'' property.
However, if some user agent setting has globally disabled image animations,
even images that could otherwise be animated are considered [=static images=],
and do not match.
Terminology {#terminology}
==========================
- static image
-
Images where a single frame is intended
to be displayed as the final viewing experience.
A JPEG image is a [=static image=].
- animated image
-
Images where multiple frames are intended
to be displayed sequentially as part of the final viewing experience,
possibly though not necessarily looping.
An animated PNG image,
or an animated [[GIF]] image
are [=animated images=].
Support for progressive rendering or multi-pass loading
does not make an image qualify as [=animated image|animated=].
- content image
-
An element of the host language representing a [=static image=]
or an [=animated image=],
at the exclusion of [=videos=] or [=programmatic images=].
The <{img}> [[HTML]] element,
including when it is nested in the <{picture}> element;
the <{object}> [[HTML]] element, in cases where it represents an image;
or the <{image}> [[SVG2]] element
represent [=content images=].
When it represents its poster frame (and only then),
the HTML <{video}> element
is considered a [=content image=].
- decorative image
-
An image inserted into the document rendering by CSS,
through such properties as `background-image` or `border-image`.
- video
-
An element of the host language representing a moving picture,
typically though not necessarily accompanied by sound,
typically though not necessarily presented with interactive controls
(for playing, pausing, seeking, controlling the volume, presenting in full screen…),
possibly though not necessarily accompanied by captions or subtitles.
Note: From a conceptual point of view, and only based on file formats,
[=videos=] and [=animated images=] have considerable overlap,
and cannot not necessarily be distinguished from one another in principle.
The distinction here is based on author intent,
as expressed through the choice of element in the document.
The <{video}> [[HTML]] element represents a [=video=].
Assuming a user agent which would support both usages,
the same video/mp4 file
would be considered a [=video=] if presented via the <{video}> element,
or a [=decorative image=] if used as a CSS `background-image`.
- programmatic image
-
An image created programmatically via an API of the host language,
as opposed to one loaded from an external resource.
The <{canvas}> [[HTML]] element represents a [=programmatic image=].
- cover frame
-
Some [=animated image=] formats make it possible
for the creator of the image
to specify a [=static image=],
referred to in this document as the [=cover frame=],
to display when the animation is not running,
distinctly from the initial state of the animation.
Accessibility Considerations {#a11y}
====================================
This section is non-normative.
-
The features introduced by this specification enable authors
to address what would otherwise be a violation
of [[WCAG22#pause-stop-hide]].
-
Web pages can already contain animated images,
and appropriate <{img/alt}> text is already expected to be provided.
No change is expected nor necessary to accommodate for pausing/resuming animations.
Descriptions like
”Cartoon coyote being squashed by a falling anvil“,
“cute dancing hamster”,
“under construction”,
or “rotating loading indicator”
remain equally appropriate and evocative
whether the animation is running or not.
-
Currently, screen readers typically do not chose to announce animated images
differently from non-animated images,
though this could be implemented if found desirable.
Similarly, it is not expected that they would announce paused or playing images any differently,
though this could be implemented if found desirable.
-
As discussed in [[#animated-image-pseudo]],
authors building UI to control image animation
need to take the usual precautions
in order to build an accessible UI.
As it is not possible to directly make an element focusable in CSS,
proper keyboard navigation will require element attributes to be set as well.
An alternative solution,
instead or in addition to letting authors build their own UI
on elements where the '':animated-image'' pseudo class matches,
would be to enable authors to instruct the user agent
to provide the UI itself when appropriate.
For example, an additional ''controlled'' value
for the 'image-animation' property could be defined.
When this value would be specified,
initially, the image animation would not run,
as if ''paused'' has been specified.
Additionally,
if the underlying [=content image=] actually is an [=animated image|animated=] one,
the user agent would provide some UI to allow the user to play and pause the animation,
and would also make the element focusable.
If necessary, this can be added to a later version of this specification.
However,
it is uncertain whether authors would broadly use this,
as they frequently prefer to design UI controls
specifically tailored to their site.
This specification therefore chose
to defer working out the complexity of such a solution
until author demand is confirmed.
Privacy Considerations {#priv}
==============================
This section is non-normative.
The 'image-animation' property enables control over image animation cross origin,
without leaking any information about whether the image is actually animatable or not.
The computed value does not change based on this information.
The `running` value has effects that are visibly different on [=animated images=]
vs [=static images=],
but none of these differences are observable by the page itself.
However, the '':animated-image'' pseudo class does reveal
whether a [=content image=] is [=animated image|animated=] or [=static image|static=],
which the page could not otherwise know cross-origin.
This could be restricted via CORS,
but this specification chose not to impose such restriction,
for the following reasons:
* There is not much to be gained from this information that isn't already known.
* Whether an image is present at the target URL at all
can reveal important information about the user
(e.g. whether they are logged in in a particular domain),
but that is already knowable from image dimensions,
and animatability does not meaningfully add to this risk.
* It is in practice very unlikely that a site would be designed to serve
both a static and an animated image from the same URL,
choosing which to serve based on some user-dependent private information
which would thereby get leaked.
* Similar information is already being shared for videos:
the HTML <{video}> element exposes duration even for cross-origin videos.
A static image is arguably a special case of an animated one with a duration of 0,
so exposing that information is analogous.
* There is a proposal to allow images in the `
Security Considerations {#sec}
==============================
This section is non-normative.
This specification is not known to introduce any new security issue.
Changes {#changes}
==================
Since the First
Public Working Draft of 9 April 2026