Re: [csswg-drafts] [css-images] Disabling image animation (#1615)

> @tabatkins: At that level, it's something the UA should be applying, not something the page author is in charge of.

### Use Cases

There are some common use-cases these days for site-specific control:

- GIF pickers will pause all gifs until the user hovers or focuses the item.
- Chat/Social apps will pause animated gifs/stickers/custom emoji/reactions/etc after playing them once on receipt, and allow the user to replay it.
  - Note: Limiting replays would likely require
- Apps with large virtualized lists will pause animated images while the user is scrolling fast for better performance.

### Today's Solutions

Often the solutions to this are one of the following:

1. **Convert all animated images to videos and use normal video playback controls**
   - On the server, this can get very expensive.
   - For some apps, this is not an option because of video encoding patents issues.
   - Video formats with alpha channels have less broad device/app support.
2. **Generate a static image ahead of time and use <picture>**
   - Additional storage costs
   - Requires JavaScript to toggle animation on "intent"
3. **Generate a static image in the browser on the fly**
   - Hurts rendering performance
   - Limited to pausing at the first frame unless you have a decoder on the client
   - Requires you to download the entire image
     - _(Note: HTML/CSS support for pausing animated images wouldn't fix this)_
   - Requires JavaScript to toggle animation on "intent"

> Here's a demo of the second and third approaches: https://codepen.io/thejameskyle/pen/XJWWJox?editors=1010

### Modeling solution after `animation-*`

Requirements like "Playing a GIF once on load" would require separate properties that would work like `animation-iteration-count`, and I think being able to pause an animated image at the current frame would be more useful than reverting back to the first frame.

Borrowing the naming scheme from `animation-*` I think that would mean:

```css
image-animation-play-state: running | paused;
image-animation-iteration-count: auto | infinite | <number>; /* auto = use image's value */
```

These additional properties from `animation-*` could maybe be useful, and if you're already decoding the image into frames wouldn't be much additional work to support, but I don't think that they are as important:

```css
image-animation-delay: <time>;
image-animation-duration: <time> /* maybe also <percentage> */;
image-animation-direction: normal | reverse | alternate | reverse-alternate;
```

### Example

Being able to disable the animation more reliably would improve this dramatically:

```css
@media (prefers-reduced-motion) {
  .gif-picker-item,
  .custom-animated-emoji,
  .message-attachment-animated-image,
    &:not(:hover, :focus, :active) img {
      image-animation-play-state: paused;
    }
  }
}

.scroller.scrolling-fast img {
  image-animation: none;
}

.message-attachment-animated-image-paused {
  image-animation: none;
}
```

Alternatively, if the new property is specified to pause animations at the _current frame_ it could be `image-animation-play-state: paused`.

### Related: Container style queries with `<source>`

Separately, I think that `<source>` supporting container `style()` queries could help the case where you do have a static image to reference.

> Note: This doesn't completely negate the need for `image-animation-play-state: paused`. I think you'd actually use these approaches together to avoid loading the static image when it won't be used, and then when you want to pause the image at its current frame you could use `image-animation-play-state: paused`

<details>
<summary>Example</summary>

```css
:root {
  --image-animations: auto;
  @media (prefers-reduced-motion) {
    --image-animations: none;
  }
  &.user-setting-reduce-motion-animated-images {
    --image-animations: none;
  }
}

.gif-picker-item,
.custom-animated-emoji,
.message-attachment-animated-image {
  container-type: normal;
  &:is(:hover, :focus, :active) {
    --image-animations: auto;
  }
}

.scroller.scrolling-fast img  {
  /* pause animations even if we haven't loaded the static image */
  image-animation-play-state: paused;
}
```

```html
<picture>
  <source srcset="example-static.png" container="style(--image-animations: none)">
  <img src="example-animated.gif">
</picture>
```

</details>

-- 
GitHub Notification of comment by jamiebuilds
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/1615#issuecomment-2652101726 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Tuesday, 11 February 2025 21:24:48 UTC