多状态卡片应使用单容器加class切换而非display:none,确保transition、View Transitions及可访问性正常;所有状态区域共存于.card内,通过opacity/visibility控制显隐,并同步更新aria属性与焦点。

多状态卡片用单容器 + class 切换,别用 display:none
display:none 会把元素完全踢出渲染树,后续 transition、3D 变换、View Transitions 全部失效。真实项目里,所有“状态”(比如详情展开、编辑态、加载中、错误态)必须共存于同一个 .card 容器内,靠 CSS class 控制显隐逻辑。
推荐结构:<div class="card">
<div class="card-content">...</div>
<div class="card-edit-form">...</div>
<div class="card-loading">...</div>
</div>。每个子区域默认 opacity: 0; visibility: hidden;,激活态加 is-active 类后改 opacity: 1; visibility: visible;,transition 写在 opacity 和 visibility 上。
- 不要给非活跃面板加
display: none—— 它会让 View Transitions 拍不到旧快照,Safari 中翻转动画直接卡死 - 如果用
max-height做展开收起,记得设overflow: hidden,且初始值不能是0(部分浏览器不触发 transition),建议用max-height: 0.01px - 多个状态之间切换时,先统一移除所有
is-active,再给目标加 —— 避免残留 class 导致样式冲突
状态切换必须同步 aria 属性和焦点
光改样式不够。屏幕阅读器依赖 aria-hidden、aria-expanded、tabindex 等属性判断当前状态。JS 切换 class 的同时,必须同步更新这些属性,否则键盘用户会迷失在不可见却仍可聚焦的元素里。
例如详情展开:给卡片容器加 is-expanded 类的同时,按钮要设 aria-expanded="true",内容区加 tabindex="0" 并调用 element.focus();收起时则反向操作。
立即学习“前端免费学习笔记(深入)”;
- 不要只读
element.classList.contains('is-expanded')来判断状态 —— DOM 和 JS 可能不同步,优先读button.getAttribute('aria-expanded') === 'true' - 用
hidden属性替代aria-hidden="true"更稳妥,它对辅助技术兼容性更好,且会自动禁用 focus - 切换后立即
focus()到新激活的内容区首元素,否则键盘用户得按多次 Tab 才能进入
卡片翻转(front/back)不能和 tab 切换混用 display 控制
标签页切换若用 display: none 隐藏非当前项,会导致卡片翻转容器(.card-inner)失去子元素,transform-style: preserve-3d 退化为 2D,Safari 中翻转直接失效或错位。正确做法是保持单个 .card 结构,只替换 .card-front 和 .card-back 的 innerHTML。
每个 tab 对应一组数据对象,点击时调用函数:updateCardContent({ front: ..., back: ... }),然后切 is-flipped 类触发动画。
- 翻转动画的
transition必须写在.card-inner上,不是.card或.card-front - 移动端必须用 JS 绑定 click,
:hover在手机上不可靠,:active无法维持状态 - 防连点:在
transitionstart事件里临时加pointer-events: none,transitionend后恢复
View Transitions API 要求 DOM 同步更新,不能塞 fetch
想用 document.startViewTransition() 实现卡片状态平滑过渡,必须确保传入的回调里是同步 DOM 操作。如果先 fetch 数据再更新,快照就拍歪了,动画直接不触发。
正确流程:先拿到完整 HTML 字符串(或预渲染好的 DOM 片段),再进 startViewTransition 回调里执行 replaceChildren() 或 innerHTML = ...。
-
view-transition-name必须成对、唯一、稳定 —— 新旧元素都得有style="view-transition-name: card-title",大小写敏感,不能带动态 ID - 过渡前目标元素不能是
display: none、visibility: hidden或opacity: 0,否则快照捕获失败;可用opacity: 0.001占位 - 该 API 不适用于跨页面跳转,只管单页内 DOM 替换;MPA 场景下别硬套



















