虽原生支持无障碍折叠,但存在open属性兼容性差、summary布局易崩、无平滑动画及cms富文本语义破坏等问题,需针对性规避。

直接用 <details></details> 和 <summary></summary> 就能实现原生、无障碍、无 JS 的折叠面板,但浏览器默认样式和交互细节容易翻车。
为什么 <details></details> 默认展开状态不可靠
<details open></details> 看似简单,但部分旧版 Safari(≤15.4)和某些 Android WebView 会忽略 open 属性,导致本该展开的面板仍收起。这不是 bug,是规范允许的“可选支持”。
- 若需强保证初始展开,必须搭配 JS 检测并手动
element.open = true - 服务端渲染时,
open属性虽存在,但首次渲染仍可能闪动(先收再展),建议加display: blockCSS 强制初始可见 - 不要依赖
open做逻辑判断——它只是 UI 状态,不是数据状态
<summary></summary> 里放什么内容才不会被截断或错位
<summary></summary> 默认是 inline 元素,且自带 ::marker(小三角),一旦里面塞了 <div> 或设了 <code>display: flex,就容易崩布局或丢失箭头。
- 只放行内内容(文本、
<span></span>、<strong></strong>),避免块级元素嵌套 - 如需图标对齐,用
background-image+padding-left替代伪元素,避免干扰 ::marker - 移动端点击热区太小?给
<summary></summary>加padding: 12px,别用min-height—— 它不影响点击区域
如何让折叠动画平滑而不是“啪”一下弹开
<details></details> 本身不支持 CSS 过渡,因为 <details></details> 展开时内部内容高度从 0→auto,而 height: auto 无法过渡。
- 方案一:用
max-height+overflow: hidden模拟,但需预估最大高度(比如设max-height: 500px),否则动画会卡顿 - 方案二:用 JS 监听
toggle事件,读取scrollHeight后设置height过渡 —— 更准但多一层维护成本 - 别用
opacity单独过渡,用户看不见内容变化,体验割裂
真正麻烦的不是写法,而是当 <details></details> 套在 CMS 输出的富文本里时,<summary></summary> 可能被自动包裹 <p></p>,破坏语义结构;这时候得后处理 DOM,或者干脆放弃原生标签改用 JS 实现。











