原生+无需JS即可实现语义化、可访问的折叠效果;必须为首个直接子元素,否则点击无响应;支持键盘操作与屏幕阅读器,但动画、多组联动及旧版Safari兼容需CSS或JS补足。

原生 <details></details> + <summary></summary> 是最轻量、语义正确、可访问性最好的方案,不需要 JS 就能工作;但想加动画、控制多组联动、或兼容老 Safari,就得绕开默认行为,用 CSS 或 JS 补足。
为什么直接写 <details><p>内容</p>
<p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill10828" title="财经HTML高端海报生成"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20dbae7c507.jpg" alt="财经HTML高端海报生成" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill10828" title="财经HTML高端海报生成">财经HTML高端海报生成</a>
<p>复杂得财经如何变成清晰,适合手机看的海报?如何加上你的IP</p>
</div>
<a href="/xiazai/skill10828" title="财经HTML高端海报生成" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div></details> 没反应
因为 <summary></summary> 必须是 <details></details> 的**第一个直接子元素**,中间不能有换行、空格或其它标签。浏览器会忽略非法结构,导致点击无响应。
- ✅ 正确写法:
<details><summary>标题</summary><p>内容</p> <p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p></details> - ❌ 错误写法:
<details><br><summary>标题</summary><p>内容</p> <p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p></details>(<br>破坏父子关系) - ❌ 错误写法:
<details><p>说明文字</p> <summary>标题</summary><p>内容</p> <p><span>立即学习</span>“<a href="https://pan.quark.cn/s/cb6835dc7db1" style="text-decoration: underline !important; color: blue; font-weight: bolder;" rel="nofollow" target="_blank">前端免费学习笔记(深入)</a>”;</p></details>(<summary></summary>不是首子元素) -
<summary></summary>内部禁止嵌套<button></button>或<a></a>—— 它们会拦截点击事件,导致原生展开失效
怎么让 <summary></summary> 看起来像按钮又不翻车
别用 display: block 覆盖默认 display: list-item,也别用 appearance: none 或 list-style: none 粗暴清空——这会让屏幕阅读器丢失状态,键盘用户无法聚焦。
- 隐藏原生箭头:用
summary::marker { content: ""; },再补自定义图标(如summary::before) - 旋转动画要生效:给
summary::before加transition: transform 0.2s,再用details[open] summary::before { transform: rotate(90deg); } - 确保
tabindex可达:不要设pointer-events: none,也不要移除<summary></summary>的原生焦点样式 - 需要“禁用”某处折叠?别加
disabled(无效),而是移除<summary></summary>,或用 JS 阻止toggle事件
Safari ≤15.4 中 details.open = true 不生效怎么办
这个版本的 Safari 对 JS 动态设置 open 属性支持极差:DOM 上已标记 open,但视觉仍收起。不是代码写错,是浏览器 Bug。
- 初始化就展开?直接在 HTML 写
<details open></details>,别依赖 JS - 运行时切换?优先用
details.toggle()方法,它比赋值open更可靠 - 仍卡住?在
DOMContentLoaded后读一次details.offsetHeight强制重排,再调用toggle() - 监听用户操作?只监听
toggle事件(它只在用户触发后派发),别监听click或属性变更
想要高度过渡动画,max-height 为什么总出问题
原生 <details></details> 不支持 height 过渡,而 max-height 是常见替代方案——但它必须设具体数值,设小了截断文字,设大了动画拖沓,且内容动态加载时高度不可预知。
- 安全做法:预估最大高度(比如最多 6 行 × 行高 ≈ 300px),设
max-height: 300px,收起时设为0并加overflow: hidden - 动态内容?先设
max-height: 0,再读element.scrollHeight,然后设max-height: ${scrollHeight}px - 图片加载中?等
img.onload触发后再执行高度测量,否则scrollHeight为 0 - 更干净的选择:放弃高度动画,只用
opacity和transform: scaleY(),视觉连贯且无需测量
真正难的不是写出折叠效果,而是保证它在键盘导航下不跳失、在屏幕阅读器里有状态播报、在图片加载完成前不闪动、在 Safari 旧版里不静默失败——这些细节不处理,用户一上手就卡住。


















