和 可原生实现无障碍、seo 友好的可折叠 faq,无需 js;需避免自闭合写法、正确使用 open 属性,遵循语义结构与 css 微调规范,并为 ie 提供轻量 polyfill 降级。

用 <details></details> 和 <summary></summary> 实现可折叠 FAQ 最省事
现代浏览器原生支持,不用 JS 就能展开收起,语义正确、无障碍友好、SEO 友好。IE 不支持,但 Chrome/Firefox/Safari/Edge(16+)都行。
常见错误是把 <summary></summary> 写成自闭合标签(<summary></summary>),它必须有结束标签;另外 <details></details> 默认展开需加 open 属性,不加就是默认收起。
-
<details></details>包裹整个问答项,每个<details></details>是独立的,互不影响 -
<summary></summary>只能是<details></details>的第一个子元素,且只能有一个 - 内容正文直接跟在
<summary></summary>后面,无需额外容器(如<div>),避免嵌套过深影响可访问性 <pre class="brush:php;toolbar:false;"><details><summary>网页加载慢怎么办?</summary> 可检查网络请求、压缩图片、启用 Gzip,或使用 <code><link rel="preload"></code> 提前加载关键资源。 </details><details open><summary>如何让文字居中?</summary> 块级元素用 <code>text-align: center</code>(文本)或 <code>margin: 0 auto</code>(块本身),注意 <code>display</code> 类型影响。 </details></pre> <h3>手动控制展开状态时别直接操作 <code>open属性虽然
element.open = true看似可行,但会绕过浏览器内置的过渡和焦点管理,导致键盘用户按 Enter 无法触发、屏幕阅读器播报异常、动画卡顿。正确做法是监听
toggle事件,用element.hasAttribute('open')判断当前状态,需要干预时调用element.setAttribute('open', '')或element.removeAttribute('open')—— 这样才能触发浏览器原生行为。- 不要用
element.style.display = 'block'模拟展开,破坏语义和可访问性 - 避免在
click事件里反复toggleAttribute('open'),可能和原生<summary></summary>点击冲突 - 若需统一收起其他项(单选式 FAQ),应在
toggle事件中遍历兄弟<details></details>并移除它们的open属性
CSS 排版微调:去掉默认箭头和控制间距
Chrome 和 Safari 默认在
<summary></summary>左侧加小三角,Firefox 不加。想统一或隐藏,得用::marker或重置list-style。常见误区是只写
summary { list-style: none },但不够——某些浏览器仍显示箭头,必须加上summary::marker { content: "" }才彻底清除。- 用
summary { padding-left: 1em }替代默认缩进,避免箭头消失后文字贴边 -
details[open] > summary可单独设置展开时的样式(比如加下划线或变色) - 正文内容默认有上下 margin,若需紧凑排版,建议对
details > *:not(summary)设置margin-top: 0.5em而非全局重置
兼容 IE 或老版本 Edge 时的降级方案
IE 完全不识别
<details></details>,所有内容默认展开且不可交互。不能靠 CSS 修复,必须用 JS 补充逻辑,但要注意别让现代浏览器重复执行。最轻量的做法是检测
'open' in document.createElement('details'),为不支持的环境动态插入按钮、绑定 click、切换aria-expanded和hidden属性 —— 不要替换整个 DOM 结构,保持 HTML 原样可读。- 降级后务必补全
aria-controls和id关联,否则屏幕阅读器无法理解问答关系 - 避免用
display: none控制显隐,优先用hidden属性,更语义且兼容 JS 失效场景 - 如果项目已用 jQuery,别写
$('details').detailsPolyfill()这类过时插件,现在有更小更靠谱的details-element-polyfill(仅 2KB)
真正麻烦的不是代码怎么写,而是很多人忘了给
<summary></summary>加tabindex="0"(其实不用——它天生可聚焦),或者在 polyfill 里漏掉键盘事件(Space/Enter 触发切换)。 - 不要用











