原生details+summary是手风琴最佳方案,支持无障碍和纯CSS控制,但IE及旧Edge不兼容;需用aria-expanded+JS降级处理。

手风琴用 details 元素最省事,但得知道它不支持 IE
现代浏览器里,details + summary 是原生手风琴方案,不用 JS 就能展开收起,图标还能用 ::marker 或伪元素控制。但注意:details 在 IE 和旧版 Edge(≤18)完全不支持,如果项目要兼容这些,得换方案。
常见错误是直接给 summary 加 onclick 或强行用 div 模拟,反而破坏语义和可访问性。正确做法是信任原生行为,只用 CSS 去修饰。
-
summary默认带小三角,Chrome/Firefox 支持list-style: none+::marker覆盖,Safari 目前不支持::marker,得用summary::before+content - 展开时
details[open]会生效,可用它来切换图标方向(比如 ▼ → ▲) - 不要给
summary设display: block,它默认是list-item,改了可能让 marker 失效
用纯 CSS 实现图标旋转动画,关键在 transform 和 transition
想让箭头点击后顺滑翻转,不能只靠 rotate(180deg),得配对设置 transition 和初始状态。否则会出现“点一下才动、再点没反应”或“动画卡顿”的问题。
示例中常用 summary::after 插入 ▼ 符号,然后在 details[open] summary::after 里加旋转:
立即学习“前端免费学习笔记(深入)”;
summary::after {
content: "▼";
margin-left: 8px;
display: inline-block;
transition: transform 0.2s ease;
}
details[open] summary::after {
transform: rotate(180deg);
}
- 必须给
transition写在未展开状态,否则首次展开无动画 - 避免用
transform: rotateX或 3D 变换,某些安卓 WebView 会渲染异常 - 图标用 Unicode 字符比引入字体图标更轻量,也避免 FOUC(闪动)
需要兼容 IE?用 aria-expanded + JS 切换 class 更可控
IE 下只能放弃 details,改用 button + div 组合,并手动管理 aria-expanded 属性和 class。这不是倒退,而是为了可访问性和一致性。
核心逻辑就三步:监听按钮点击 → 切换相邻 div 的 hidden 状态 → 同步更新 aria-expanded 和图标 class:
<button aria-expanded="false">标题 <span class="icon">+</span></button> <div hidden>内容区</div>
- 别用
display: none控制显隐,它会让屏幕阅读器彻底忽略内容;用hidden或aria-hidden配合视觉隐藏更稳妥 - 图标 class 切换建议用
icon-open/icon-closed,而不是依赖 JS 动态拼字符串 - 记得在 JS 里补上键盘支持:Enter/Space 键也要触发展开
图标对齐总出问题?检查 line-height 和 vertical-align
图标和文字看起来“上下偏移”,大概率是 line-height 不一致或 vertical-align 默认值作祟。特别是用 span::before 插入图标时,它默认按 baseline 对齐,而文字有 descender(如 g、y),就会显得图标偏高。
- 统一设
vertical-align: middle或-webkit-font-smoothing: antialiased减少锯齿干扰 - 如果用 SVG 图标,确保
height和vertical-align匹配父元素的line-height - 移动端 Safari 对
line-height计算较敏感,建议用无单位数值(如line-height: 1.4)而非px
真正麻烦的不是怎么加图标,而是不同浏览器对 summary 的 marker 渲染策略不统一,以及动画帧率在低端安卓机上容易掉帧——这些没法靠一次写完 CSS 解决,得实测目标设备。



















