配了八年 GIF,今天才发现 CSS 从来管不了它内部——Chrome 152 今天把这件事彻底原生化了
你有没有遇到过这种情况:页面上有个 GIF 动画,设计师说「这里要能暂停」,然后你翻了半天文档发现——对不起,没有标准 API,要么靠 JavaScript 操作 DOM 把图片 src 换成静态帧,要么直接告诉产品「浏览器不支持」。
这不只是你一个人的困境。WCAG 2.3.3 早就在要求「交互动画必须可关闭」,但 CSS 从来就没有一个正经属性来管图片动画。浏览器自动播放 GIF,开发者管不着,这个局面一直持续到了 Chrome 152。
Chrome 152(2026 年 8 月)正式把 image-animation 属性默认启用了。
这是 CSS 第一个真正管到 <img> 内部动画的标准属性。GIF、WebP 动画、APNG——全都在它的管辖范围内。
一行让整个页面安静下来
/* 暂停页面上所有图片动画 */
:root {
image-animation: paused;
}
这就是最基础的用法。加上这一行,页面上所有 GIF、WebP 动画/APNG 全部停止在第一帧。不需要 JavaScript,不需要操作 DOM,CSS 直接告诉浏览器:「这些图片别播」。
有人会说:「那我直接用 CSS 把动画全关掉不就行了?」问题是 animation 属性只管 CSS @keyframes 动画,管不到 <img> 标签里的 GIF 动画。image-animation 是第一个能管到图片素材本身动画的属性。
有选择地暂停:装饰性动画停掉,功能性动画留着
无脑全局暂停有个问题:loading 指示器也是 GIF 或者 APNG,你把它停掉,用户就不知道页面还在加载了。
所以正确的用法是:先全局暂停,再把功能性动画单独放行。
/* 全局暂停 */
:root {
image-animation: paused;
}
/* loading 指示器允许播放 */
.loading-indicator {
image-animation: running;
}
有人会说:「那我直接用 CSS 把动画全关掉不就行了?」问题是 animation 属性只管 CSS @keyframes 动画,管不到 <img> 标签里的 GIF 动画。image-animation 是第一个能管到图片素材本身动画的属性。
:animated-image 伪类:自动识别动画图
但这里有个问题:怎么知道哪个图片是动画,哪个是静态图?靠类名太脆弱,你没法保证设计师上传的每个 loading 图都带类名。
:animated-image 伪类就是来解决这个问题的。
/* 只有动画图片的 loading-indicator 才放行 */
.loading-indicator:animated-image {
image-animation: running;
}
:animated-image 表示「已加载的图片来源是动画格式」。如果是静态图,这个选择器根本不会匹配。相当于浏览器帮你做了一个格式检测,你只需要写选择器就行。
配合 prefers-reduced-motion:用户说关,就全关
image-animation 真正的价值在于和 prefers-reduced-motion 的配合。
/* 用户系统设置里勾了「减少动画」 */
@media (prefers-reduced-motion: reduce) {
:root {
image-animation: paused;
}
/* 功能性动画降级为只播一次,然后暂停 */
.loading-indicator:animated-image {
image-animation: once paused;
}
}
once paused 是一个组合值:播放一轮动画,然后暂停。这对于 loading 指示器特别有用——用户不需要看无限循环的转圈,但他们需要知道「这里有东西在加载」。
controlled 值:把控制权还给用户
还有一个更激进的模式——controlled。
/* 默认暂停,由用户提供播放触发 */
.decorative-gif {
image-animation: controlled;
}
controlled 语义是:图片默认暂停,如果用户想看,浏览器会在图片上显示一个原生的播放按钮,用户点击后才开始播放。这和 <video controls> 的逻辑一致——浏览器自己提供 UI,不需要你写任何 JavaScript。
这个值对于营销类 GIF 特别有用。比如电商详情页里那些展示产品使用步骤的 GIF——它们是装饰性的,用户不一定要看,但有人想看的话可以点开。
为什么这件事 WCAG 早就在要求,但 CSS 一直没做
WCAG 2.3.3(AAA 级)要求:「由交互触发的动画,除非必要,否则必须可关闭。」但长期以来,CSS 能关闭的只有 CSS @keyframes 动画,GIF 动画完全不在 CSS 的管辖范围内。
这导致一个荒谬的局面:你可以用 CSS 让一个 <div> 的晃动动画停止,但没法让同一个页面上的一张 GIF 停止。只能用 JavaScript 换 src,或者靠浏览器扩展。
根本原因是:GIF 动画是图片格式本身的特性,CSS 历史上没有对应的概念。image-animation 是 CSS 第一次把图片格式的动画能力纳入标准控制范围。
浏览器支持现状
Chrome 152(2026 年 8 月)默认启用,Android 和 WebView 同版本跟进。Firefox 和 Safari 暂时没有明确信号。
由于目前只有 Chromium 系支持,渐进增强写法是:
/* 不支持的浏览器完全不处理,不影响原有行为 */
@supports (image-animation: paused) {
@media (prefers-reduced-motion: reduce) {
:root {
image-animation: paused;
}
}
}
@supports 保证了这段代码只在浏览器支持时才生效,不支持的浏览器直接忽略,不会有任何副作用。
三个坑
第一个坑:image-animation 管的是图片格式的动画,不是 CSS 动画。 如果你页面上有个 CSS @keyframes 动画,这个属性管不到它。所以 prefers-reduced-motion 的完整实现通常需要两个配合:
@media (prefers-reduced-motion: reduce) {
/* 关 CSS 动画 */
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
/* 关图片动画 */
:root {
image-animation: paused;
}
}
两者配合才能覆盖所有动画类型。
第二个坑:image-animation: running 不会让静态图动起来。 如果一张图本身就是静态的(PNG/JPEG),设置 running 不会有任何效果。这不是 bug,是设计逻辑:属性控制的是「播放状态」,不是「格式」。
第三个坑:prefers-reduced-motion 是用户设置,不是页面开关。 不要在你的 UI 里加一个「关闭动画」的按钮来替代系统设置——那只是在你的页面里模拟了系统设置的行为,但用户在其他网站遇到动画仍然没法关。正确的做法是:始终尊重 prefers-reduced-motion,不做自己的动画开关 UI。
现在可以用了吗
如果你面向的用户主要在 Chromium 浏览器(全球桌面浏览器 Chrome+Edge 合计占比很大),image-animation 加上 @supports 渐进增强可以安全上线。
对于 Safari/Firefox 用户,这段 CSS 会被忽略——GIF 仍然自动播放,这是 2026 年 9 月的现状。如果你需要完整覆盖,考虑在服务端对 GIF 做静态帧替换作为 fallback。
三步下一步:
- 先做审计:在 Chrome 里打开 DevTools,选中所有
<img>标签,看 Network 面板里哪些请求的 MIME 类型是image/gif或image/webp,这些就是你的动画图片 - 找 loading 指示器:把它们标记上
.loading-indicator类,然后加image-animation: running例外 - 加
@media (prefers-reduced-motion):把image-animation: paused写进你的全局 reduced-motion 媒体查询里,配合现有的 CSS 动画关闭规则一起用
GIF 动画从来不归 CSS 管——这个局面,Chrome 152 今天给关了。
评论区
登录后可评论。