原生是最快、最语义化且无障碍支持最佳的折叠组件,无需JS即可响应键盘操作,但默认不互斥、无动画、样式受限。

原生 + 就是最快、最语义化、无障碍支持最好的折叠展开框,不需要 JS 也能响应键盘操作;但默认不互斥、无动画、样式受限,别指望它“开箱即用”就满足所有设计需求。
用 和 搭建基础容器
这是唯一无需 JS 就能天然支持空格/回车触发、屏幕阅读器播报、焦点管理的方案。关键点很实在:
-
必须是的第一个子元素,写成或塞在里都会失效 - 默认收起,加
open属性可默认展开:<details open><summary>标题</summary>内容</details>
- Safari 15.4+ 才修复
的 focus 样式 bug,旧版中点击后可能失焦,别依赖 outline 样式做状态反馈 - 不要给
或设height或display: none—— 这会破坏可访问性,且部分浏览器直接忽略
让多个 实现手风琴(单开)效果
原生允许多开,要单开必须加 JS 控制 open 属性。监听 toggle 事件是唯一可靠方式,click 会漏掉键盘操作。
- 给所有面板加统一 class,比如
class="accordion-item" - 监听父容器上的
toggle事件(推荐事件委托),或遍历每个单独绑定 - 只在当前项
event.target.open === true时,对其他同组项调用.removeAttribute('open')—— 别用.open = false,否则会再次触发toggle,造成循环 - 动态插入的新
不会自动继承逻辑,要么重新绑定,要么改用委托
加平滑展开动画:绕过 的限制
原生不支持 height 或 max-height 过渡,因为内容高度是动态计算的。想有动画就得自己接管高度控制。
- 放弃
的原生交互,改用+max-height+overflow: hidden+ JS 测高- 展开前读取目标内容的
scrollHeight,设为max-height;收起时设为0overflow: hidden必须始终存在,否则动画中内容会溢出- 别硬写死
max-height: 500px,长内容会被截断,短内容动画拖沓- 如果内容含图片或字体加载延迟,
scrollHeight可能不准,需监听load或fontloaded后重设自定义图标和样式时容易踩的坑
原生箭头不可靠,Safari 对
::marker支持差,得用::before补图标,但旋转动画要小心。- 隐藏默认箭头最稳写法:
summary { list-style: none; },比summary::marker { content: ""; }兼容性好 - 加旋转图标用
summary::before,配合details[open] summary::before { transform: rotate(90deg); } -
transform动画必须配transition,且transform-origin建议设为left center避免偏移 - 别在
里放或链接——点击会冒泡触发折叠;要么加event.stopPropagation(),要么把按钮挪到外、内
真正难的不是搭出能动的框,而是确保键盘用户能 tab 进去、屏幕阅读器能念出状态、小屏下不会挤出横向滚动条、图片还没加载完时高度也不崩。这些细节一旦漏掉,再漂亮的动画也白搭。
- 展开前读取目标内容的
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











