最简实现是用原生details+summary元素,无需JS、自动支持键盘操作和ARIA状态;错误做法是手动div+onclick;IE不支持,需降级时应采用aria-expanded+hidden的WCAG合规方案。

点击后展开/收起内容的最简实现
直接用 details + summary 元素,浏览器原生支持,无需 JS,兼容性到 Chrome 12 / Firefox 49 / Safari 6(iOS 6+),连 IE 都不支持——但如果你不需要支持 IE,这方案就是首选。
常见错误是手动写 div + onclick + 切换 display,结果样式错乱、键盘不可访问、屏幕阅读器读不出状态。原生 details 自动处理焦点、空格/回车触发、ARIA 状态(aria-expanded)、默认箭头图标。
<details> <summary>点击展开</summary> <p>这里是隐藏的内容…</p> </details>
-
summary必须是details的第一个子元素,否则无法触发 - 默认箭头在 Chrome/Firefox 可用
summary::marker覆盖,Safari 不支持该伪元素,需用summary::before模拟 - 展开时
details[open]伪类生效,可用于自定义样式(比如加边框或背景色)
需要自定义按钮文字或图标时怎么改
原生 summary 内容就是按钮文本,可直接写 HTML;图标建议用 SVG 或字体图标,避免用图片(加载失败会留白)。
容易踩的坑:给 summary 加 display: flex 后,内部图标和文字对齐错位;或者用 float 导致 summary::marker 位置异常。
立即学习“前端免费学习笔记(深入)”;
<details>
<summary>
<svg width="16" height="16" viewBox="0 0 24 24"><path d="M7 10l5 5 5-5z"/></svg>
<span>更多信息</span>
</summary>
<p>…</p>
</details>
- SVG 图标推荐内联,避免外部请求阻塞渲染
- 若要用纯 CSS 控制展开/收起箭头,Safari 下必须用
summary::before+content,且需设置summary::-webkit-details-marker { display: none; } - 不要给
summary设user-select: none,否则触屏设备长按可能误触发选中
JavaScript 手动控制 open 状态的场景
只有两种合理理由需要 JS 干预:初始状态由 URL 参数决定(如 ?section=faq),或与其他组件联动(如点击导航菜单项时展开对应 details)。
别为了“更酷的动画”强行 JS 控制——CSS 过渡对 details 的 height 无效(因为高度是自动计算的),强行加动画反而导致布局抖动或可访问性降级。
- 用
element.open = true或element.setAttribute('open', '')设置状态,后者更稳妥(兼容旧版 Safari) - 监听
toggle事件而非click,因为用户可能用键盘操作:details.addEventListener('toggle', () => console.log(details.open)) - 批量控制多个
details时,避免用querySelectorAll('details').forEach(d => d.open = false)—— 这会强制重排,应改用getBoundingClientRect()前缓存 DOM 引用
IE 或老安卓 WebView 必须支持时的降级方案
如果真绕不开 IE11 或 Android 4.x WebView,就放弃 details,改用 aria-expanded + aria-controls + 手动切换 hidden 属性,这是 WCAG 2.1 推荐的 ARIA 方案,比瞎写 display: none 更可靠。
关键不是“能动”,而是“键盘能操作、屏幕阅读器能识别、焦点管理正确”。很多所谓“兼容方案”只管视觉切换,漏掉 tabindex 和 focus(),导致残障用户无法使用。
<button aria-expanded="false" aria-controls="panel-1">点击展开</button> <div id="panel-1" hidden>内容…</div>
- 点击按钮时,同步更新
aria-expanded值和hidden属性 - 按钮必须有
type="button",否则表单内可能意外提交 - 展开后,建议用
element.focus()把焦点移到面板首个可聚焦元素(如链接或输入框),而不是留在按钮上
真正麻烦的从来不是代码几行,而是确保每次展开后焦点位置合理、键盘 Tab 顺序不跳断、语音朗读时能明确说出“已展开”或“已收起”。这些细节没做,再漂亮的动画也没用。



















