原生details/summary标签交互语义正确、零JS、无障碍友好,但无内置动画;自定义动画需JS配合CSS控制max-height,注意scrollHeight计算时机及Safari兼容性。

原生交互的核心优势
浏览器原生支持点击
必须是 的第一个子元素,否则交互失效- 添加 open 属性可默认展开:
<details open></details> - 多个 设置相同 name 属性,可实现单选互斥(类似 radio 组)
- 监听 toggle 事件能获知状态变化,适合做日志记录或轻量逻辑响应
箭头图标与基础样式定制
默认的三角标记可通过伪元素替换,保持语义同时提升视觉一致性。
- 清除原生 marker:
summary { list-style: none; } - 用 ::after 添加自定义箭头:
summary::after { content: "▼"; transition: transform 0.2s; } - 利用
details[open] summary::after实现旋转动画,收起时 ▼,展开时 ▲ - 避免使用
appearance: none,以免破坏键盘焦点样式
实现平滑展开动画的关键步骤
原生行为是瞬时切换,要加动画必须接管高度控制——本质是模拟,不是增强。
- 给内容区(
后的第一个兄弟元素)设 overflow: hidden - 监听
toggle事件,在展开时先设max-height: 0,强制重排,再设为scrollHeight - 收起时反向:先设目标高度,重排,再设回
max-height: 0 - 图片未加载完成时
scrollHeight可能偏小,需在img.onload后重新计算或用 ResizeObserver - Safari 对 max-height 过渡支持较弱,建议加
will-change: max-height提升渲染稳定性
什么情况下不该强行加动画
动画不是必需项,过度追求反而损害体验和可维护性。
- 内容高度差异大(如含多图、动态文本),难以预估 scrollHeight
- 仅需基础折叠功能的 FAQ、设置项,原生交互已足够清晰可靠
- 项目需支持 IE 或老旧 Android WebView,JS 方案需额外 polyfill
- 团队缺乏对重排机制的理解,容易写出卡顿或错位的动画逻辑

















