原生默认无动画,需用max-height+opacity+overflow:hidden组合实现过渡;必须用details[open]伪类控制状态;图标应内嵌于summary而非伪元素;手风琴需name属性,safari旧版需js降级。

details 默认不带动画,max-height 过渡是主流解法
原生 <details></details> 切换时只有显示/隐藏,没有过渡效果。想加淡入淡出,得绕过 display(它无法过渡),改用 max-height + opacity + overflow: hidden 组合控制视觉变化。
关键点是:把内容区域包裹进一个独立容器(比如 <div class="content">),再对它设置过渡属性;<code><details></details> 本身只负责状态管理,不直接参与动画。
-
max-height设为一个“足够大但固定”的值(如500px),模拟height: auto的渐变效果 -
opacity从 0 → 1 配合缩放或透明度变化,增强淡入感 - 必须设
overflow: hidden,否则内容会溢出破坏动画边界 - 过渡时间统一写在展开/收起两个状态里,避免反向无动画
details[open] 是触发样式的唯一可靠选择器
不能监听 click 或写 JS 来切类名——那样就失去原生语义和键盘可访问性了。details[open] 是 CSS 唯一能准确反映当前展开状态的伪类,所有动画逻辑都得基于它写。
示例片段:
details .content {
max-height: 0;
opacity: 0;
overflow: hidden;
transition: max-height 0.3s ease, opacity 0.2s ease;
}
details[open] .content {
max-height: 500px;
opacity: 1;
}
- 别用
height: 0 → height: auto:auto 无法过渡,会瞬间跳变 - 500px 不是魔法数字,要略大于你内容实际高度;若内容超长,动画会提前截断,需按需调整
- Safari ≤ 15.4 对
max-height过渡支持不稳定,建议加transform: scaleY(0)备用方案
summary 内部图标旋转比 ::marker 更可控
虽然可以用 summary::marker 隐藏默认箭头,但它的样式控制力弱、跨浏览器表现不一致。更稳妥的做法是把图标(<svg></svg> 或 <span></span>)直接写进 <summary></summary> 标签内,再用 details[open] summary svg 控制旋转。
- 确保图标是
<summary></summary>的子元素,不是伪元素,否则焦点和语义可能丢失 - 旋转用
transform: rotate(180deg),配合transition实现平滑翻转 - 不要给
<summary></summary>加role="button"或tabindex:它本就是可聚焦、可回车触发的交互元素
嵌套或手风琴场景下,name 属性容易被忽略
多个 <details></details> 想做成单选手风琴(展开一个、其他自动收起),光靠 CSS 不行,必须用 HTML 原生 name 属性:<details name="accordion"></details>。同名的 <details></details> 在同一文档中会自动互斥。
- 这个特性在 Chrome/Firefox/Edge 中稳定支持,但 Safari ≤ 16.6 有兼容问题,需降级为 JS 控制
- 如果用了 JS 手动控制
open属性,请注意 Safari 旧版不响应details.open = true赋值,得用details.setAttribute('open', '')并触发重排 - 动画层叠时,多个面板同时切换可能导致视觉卡顿,建议加
will-change: transform提升合成层
name 属性漏加、图标放在伪元素里却没处理焦点,这三处出错,用户第一眼就感觉“不丝滑”。











