是唯一原生支持可访问折叠展开的html方案;display: none仅视觉隐藏,无键盘支持、无障碍属性或seo友好性,而自带语义、焦点管理、toggle事件及自动无障碍支持。

HTML 本身没有“折叠后支持展开收起”的内置行为,<details></details> 是唯一原生支持的语义化方案;其他所谓“折叠”只是视觉隐藏,不带交互逻辑。
为什么 <div style="display: none"> 不算真正的折叠
<p>这种写法只是强制隐藏元素,既不触发键盘操作(如回车/空格),也不暴露可访问性状态(screen reader 无法感知“可展开”),更不会自动管理 <code>aria-expanded 或焦点流转。用户点击按钮后手动切 display,本质是自己实现一套不完整、不可靠的 toggle 逻辑。
- 屏幕阅读器完全不知道内容存在或可操作
- 移动端双击缩放可能意外暴露被隐藏内容
- SEO 友好性差:搜索引擎可能忽略
display: none 内容,或误判为关键词堆砌
- 无默认过渡效果,硬切
display 会破坏 CSS 动画连贯性
用 <details></details> 实现真正可访问的折叠
display: none 内容,或误判为关键词堆砌display 会破坏 CSS 动画连贯性<details></details> 实现真正可访问的折叠这是 HTML5 原生标签,浏览器原生支持展开/收起、键盘操作、焦点管理、无障碍属性,无需 JS 即可工作。
- 必须配对使用:
<details><summary>标题</summary>内容</details>,<summary></summary>必须是<details></details>的第一个子元素 - 默认带箭头图标,可用
::marker或list-style: none覆盖,但不要删掉<summary></summary>—— 否则失去语义和键盘支持 - 展开状态由浏览器控制,JS 只需监听
toggle事件:el.addEventListener('toggle', () => { ... }) - 不能直接给
height加 transition,但可通过max-height+ JS 测量做平滑动画(见下一条)
需要动画时,<details></details> + JS 测量真实高度
原生 <details></details> 不支持 CSS 过渡,要加滑动效果,得在它基础上增强,而不是弃用它。
- 监听
toggle事件,判断el.open === true表示正在展开 - 展开前先设
el.style.maxHeight = '0'和el.style.overflow = 'hidden' - 强制重排:
void el.offsetHeight,再设el.style.maxHeight = el.scrollHeight + 'px' - 收起时反向操作:先设
maxHeight为具体像素值,再设为0;动画结束后再清除maxHeight并恢复overflow: visible - 避免用
all 0.3s,只过渡max-height和opacity,否则可能触发布局抖动
旧浏览器不支持 <details></details> 怎么办
IE 完全不支持,Edge 12–18 仅部分支持(无 toggle 事件)。检测后降级为 JS 控制的 max-height 方案即可,不用重写整套 DOM 结构。
- 用
'open' in document.createElement('details')判断原生支持与否 - 不支持时,动态把
<details><summary></summary></details>替换为<div class="collapsible"><button> + <code><div class="content">,再绑定 click 事件 <li>关键点:降级后的 JS 逻辑必须复用同一套高度测量和过渡控制代码,保持行为一致</li> <li>别为了兼容 IE 强行 polyfill <code><details></details>—— 成本高、bug 多、无障碍仍难保障
真正容易被忽略的是:动画是否在展开完成后才让内容可聚焦、可滚动。如果只控制 max-height,但没同步处理 tabindex 或 overflow,键盘用户可能卡在不可见区域。原生 <details></details> 自动处理了这些,自研方案得手动补全。











