是当前最直接可靠的faq实现方式,支持无js的键盘操作、屏幕阅读器和seo;但需注意summary必须为首个子元素、不可自闭合、避免块级标签嵌套,并通过css伪元素统一处理箭头图标与锚点展开逻辑。

<details></details> 是当前最直接、最可靠的 FAQ 实现方式,不用 JS 就能支持键盘操作、屏幕阅读器播报和 SEO 友好结构。IE11 不支持,但如今基本可忽略。
为什么 <summary></summary> 必须是 <details></details> 的第一个子元素
这是最容易失效的点:只要中间夹了空格、注释、<p></p> 或 <div>,点击就完全没反应。浏览器会直接忽略折叠逻辑,连 <code>open 属性都无效。
- 错误写法:
<details><p><summary>Q:</summary></p> <p>A:</p></details>(<p></p>挡在前面) - 正确写法:
<details><summary>Q:</summary><p>A:</p></details> -
<summary></summary>不能自闭合,必须写成<summary>…</summary> - 里面别塞
<h3></h3>、<div> 等块级标签——可用 <code><strong></strong>或<span></span>替代怎么统一清除默认箭头并加自定义图标
Chrome、Safari、Firefox 对
<summary></summary>的原生::marker渲染不一致,只靠list-style: none清不干净,尤其 WebKit 内核需要单独处理。- 先清掉所有默认 marker:
summary::-webkit-details-marker { display: none; }+summary::marker { content: ""; } - 再用伪元素加图标:
summary::before { content: "▸"; margin-right: 6px; } - 展开时旋转:
details[open] summary::before { transform: rotate(90deg); }(需配display: inline-block和transition) - 顺手去掉
outline,否则键盘聚焦时样式错位
URL 锚点自动展开对应 FAQ 怎么配
用户点
faq.html#reset-password,浏览器默认只滚动,不会展开。要让它生效,得靠 CSS + 极简 JS 双保险。- 每个
<details></details>加唯一 ID:<details id="reset-password"></details> - CSS 规则(Safari 15.4+ 支持):
details:target { open: true; } - 兜底脚本(几行就够了):
const id = location.hash.slice(1); const el = document.getElementById(id); if (el && el.tagName === 'DETAILS') el.open = true; - ID 值禁用空格和中文标点;若从中文标题生成,建议转小写拼音或用
encodeURIComponent()处理后截取
多个 FAQ 互斥展开(单选手风琴)必须用 JS 吗
必须。原生
<details></details>不支持“点一个、关其他”,这是常见需求,但只能靠 JS 补足。- 监听
toggle事件,不是click—— 它才是状态真正切换的时机 - 只在
e.target.open === true时才去关别的,避免刚点开又被关掉 - 筛选目标:
document.querySelectorAll('details:not([open])'),而不是无条件遍历所有 - 示例:
document.addEventListener('toggle', e => { if (e.target.open) { document.querySelectorAll('details').forEach(d => { if (d !== e.target) d.open = false; }); } });
最易被忽略的是:样式重置不彻底会导致 Safari 点击失灵,ID 命名不规范会让锚点展开失败,而互斥逻辑里漏掉
e.target.open判断就会让交互卡顿。这些都不是边缘情况,而是上线后高频翻车点。 - 先清掉所有默认 marker:











