CSS view transitions怎样为同文档状态切换设置过渡
如果单页应用只是把列表替换成详情,传统做法通常是给容器加一个淡入动画,再手动处理旧内容的离场。CSS View Transitions 把这件事拆成了更清晰的两层:JavaScript 负责在同一个文档中提交状态变化,CSS 负责给变化前后的快照定义动画。
本文只讨论同文档状态切换,例如筛选列表、切换卡片详情或更新局部面板。官方资料入口:
官方地址:https://developer.mozilla.org/en-US/docs/Web/API/Document/startViewTransition
最小用法是把真正修改 DOM 的函数交给document.startViewTransition()。浏览器不支持该 API 时,直接执行同一个更新函数;需要独立移动的元素再设置唯一的view-transition-name。
先分清同文档和跨文档
同文档过渡发生在一个页面内部,通常由 SPA 的筛选、路由状态或组件更新触发。它的入口是 document.startViewTransition(updateCallback)。跨文档导航则是两个页面之间的导航,需要参与页面通过 @view-transition 选择加入;这不是本文的触发方式。
因此,本文的最小模型只有三块:旧状态快照、更新回调、新状态快照。浏览器在回调前记录旧状态,在回调完成后记录新状态,再让 CSS 过渡伪元素负责呈现变化。

把原来的 DOM 更新包起来
先保留一个普通的更新函数,再让按钮点击只负责选择是否通过过渡调用它。这样写的好处是降级路径和增强路径使用同一份业务逻辑,不会因为浏览器不支持新 API 而维护两套状态代码。
const panel = document.querySelector('#panel');
const toggle = document.querySelector('#toggle');
function updatePanel() {
// 这里只修改状态对应的 DOM,不在函数里重复创建过渡。
panel.classList.toggle('is-expanded');
panel.querySelector('.label').textContent = panel.classList.contains('is-expanded')
? '展开'
: '收起';
}
toggle.addEventListener('click', () => {
if (!document.startViewTransition) {
// 不支持 API 时照常更新,功能不能依赖动画存在。
updatePanel();
return;
}
// 浏览器先保存旧状态,再执行回调并生成新状态快照。
document.startViewTransition(() => updatePanel());
});
这个调用不要求你自己复制旧节点,也不需要先写一套离场节点。默认情况下,页面根快照会使用淡入淡出和尺寸变化完成基本过渡;如果只需要一个轻量状态切换,到这里就足够了。
用唯一名称把元素从 root 中拆出来
当卡片、标题或封面需要独立移动时,给它一个 view-transition-name。名称对应参与过渡的快照,必须保证同一时刻的渲染元素不重复使用同一个名称;否则过渡可能被跳过。
.product-card.is-active {
/* 这个元素会从 root 快照中拆出独立的图像对。 */
view-transition-name: active-card;
}
::view-transition-group(active-card) {
/* 组控制新旧快照的几何变化时间。 */
animation-duration: 260ms;
}
::view-transition-old(active-card) {
/* 旧卡片离场时略微缩小,避免和新状态硬切。 */
animation: card-out 160ms ease both;
}
::view-transition-new(active-card) {
/* 新卡片从轻微缩小和透明状态进入。 */
animation: card-in 220ms ease both;
}
@keyframes card-out {
to { opacity: 0; transform: scale(.96); }
}
@keyframes card-in {
from { opacity: 0; transform: scale(.96); }
}
如果列表中有多个需要独立处理的项目,不要把同一个固定名称同时写给所有元素。可以在状态更新时只给当前元素命名,也可以在适用的同文档场景使用 match-element 让浏览器分配内部唯一名称,但不要把它当成跨文档名称传递方案。

过渡伪元素负责最后的节奏
同文档过渡会暴露一组 CSS 伪元素。::view-transition-old(root) 和 ::view-transition-new(root) 控制根快照,带名称的元素则使用对应名称作为参数。可以先改持续时间和透明度,再决定是否需要更复杂的位移。
::view-transition-old(root),
::view-transition-new(root) {
/* 根状态切换保持短而稳定,避免遮住用户操作反馈。 */
animation-duration: 180ms;
}
::view-transition-new(active-card) {
/* 用自定义关键帧替换默认淡入,名称必须和元素保持一致。 */
animation-name: card-in;
}
@media (prefers-reduced-motion: reduce) {
/* 用户要求减少动效时,缩短为几乎不可感知的过渡。 */
::view-transition-group(*) {
animation-duration: 1ms;
}
}
不要把动画结果当成状态同步机制。数据和可访问性状态仍应在更新回调里完成,CSS 只负责呈现从旧快照到新快照的视觉过程。
不生效时先看三个边界
| 现象 | 优先检查 | 处理方式 |
|---|---|---|
| 点击后没有过渡 | document.startViewTransition 是否存在 | 保留直接执行更新函数的降级分支,不把动画当成业务前提 |
| 命名元素动画被跳过 | 同一时刻是否有多个渲染元素使用相同名称 | 确保名称唯一,或改用适合当前同文档列表的自动匹配方式 |
| 改了 CSS 但仍是默认淡入 | 伪元素参数是否与名称一致 | 检查 ::view-transition-old(name) 和 ::view-transition-new(name) 的 name |
最后再确认更新回调确实改变了 DOM。没有状态差异时,浏览器没有可动画的新旧内容;而在用户偏好减少动效时,应该优先保证信息更新和焦点顺序,再把动画压缩到极短。
采用前的最小清单
- 只在同一个文档内更新 DOM 时使用
document.startViewTransition()。 - 把业务更新集中到回调函数,并准备不支持 API 的直接更新路径。
- 给独立动画元素设置唯一的
view-transition-name。 - 先调伪元素的持续时间,再逐步添加位移和缩放,避免过渡遮挡操作反馈。
- 尊重
prefers-reduced-motion,不要让动画成为信息传递的唯一方式。
相关问题
同文档过渡必须使用单页应用吗?
不一定,关键是状态更新发生在同一个文档里,并且能够在回调中修改 DOM。SPA 是常见场景,但普通页面中的局部交互也可以采用相同思路。
为什么 view-transition-name 不能随便重复?
名称用于区分独立快照。多个渲染元素同时拥有同名标识时,浏览器无法建立一一对应关系,过渡可能被跳过。
@view-transition 能替代 startViewTransition 吗?
不能把两者混为一谈。本文的同文档状态切换由 JavaScript 调用 startViewTransition;@view-transition 主要用于跨文档导航的加入声明。
把 DOM 更新和视觉过渡分开之后,最小实现其实只有一个回调和一组伪元素。先确保不支持新 API 时功能仍然正常,再按元素的实际阅读关系添加唯一名称,通常比一开始复制整套动画状态更容易维护。
CSS timeline-scope怎样让不同滚动容器共享命名时间线
- 上一篇
- CSS timeline-scope怎样让不同滚动容器共享命名时间线
- 下一篇
- JavaScript Iterator.from怎样把类迭代对象统一转换
-
- 文章 · 前端 | 40分钟前 |
- JavaScript Uint8Array.fromBase64怎样避免手写 Base64 解码
- 251浏览 收藏
-
- 文章 · 前端 | 43分钟前 | 前端 · ReadableStream WebTransport HTTP/3 QUIC WritableStream WebTransport datagrams
- WebTransport datagrams怎样传递低延迟不可靠消息
- 331浏览 收藏
-
- 文章 · 前端 | 45分钟前 |
- WebSocketStream怎样用 Streams API 处理背压
- 500浏览 收藏
-
- 文章 · 前端 | 47分钟前 | CSS CSS anchor positioning position-visibility anchors-visible no-overflow
- CSS position-visibility怎样让锚定浮层随锚点离屏隐藏
- 489浏览 收藏
-
- 文章 · 前端 | 47分钟前 |
- Web Crypto Ed25519怎样生成与验证签名
- 194浏览 收藏
-
- 文章 · 前端 | 52分钟前 |
- JavaScript Iterator.prototype.drop怎样跳过前 N 个元素
- 456浏览 收藏
-
- 文章 · 前端 | 54分钟前 |
- JavaScript Iterator.from怎样把类迭代对象统一转换
- 396浏览 收藏
-
- 文章 · 前端 | 56分钟前 | 兼容性 · CSS animation-timeline timeline-scope Scroll-driven Animations scroll-timeline-name
- CSS timeline-scope怎样让不同滚动容器共享命名时间线
- 112浏览 收藏
-
- 文章 · 前端 | 58分钟前 |
- CSS animation-timeline怎样按滚动进度驱动进度条
- 346浏览 收藏
-
- 文章 · 前端 | 1小时前 | 前端 · CSS anchor positioning anchor-name position-anchor anchor-size 弹出层宽度
- CSS anchor-size怎样让弹出层宽度跟随触发按钮
- 348浏览 收藏
-
- 文章 · 前端 | 1小时前 |
- HTML details name 怎样让手风琴只展开一个面板
- 129浏览 收藏
-
- 文章 · 前端 | 1小时前 | 前端 · javascript · css · 浏览器兼容 · CSS 兼容性 表单 输入框 渐进增强 field-sizing
- CSS field-sizing 不支持时怎么给自适应输入框做降级
- 293浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 888次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 888次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 971次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 957次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 782次使用
-
- Go语言对前端领域的入侵WebAssembly运行原理
- 2022-12-31 130浏览
-
- go+gin 静态资源路由与后端api路由冲突如何解决?
- 2023-02-24 414浏览
-
- 分片上传文件,后端接收怎么生成了一个文件名为blob的文件?
- 2023-01-09 163浏览
-
- 除了cookie之外,还能用什么方法做验证码功能?
- 2023-01-22 137浏览
-
- 使用指南怎么生成
- 2023-01-18 160浏览
