分步教程需用JS控制details的open属性实现顺序引导,不能仅靠HTML;summary内禁放交互元素,应监听toggle事件而非click,并注意无障碍与滚动焦点管理。

details 标签本身不支持嵌套步骤自动展开
直接用 <details> 做分步教程,浏览器不会帮你“推进到下一步”——它只是独立的可展开/收起区块。想实现“点击下一步才显示下一项”,得靠 JS 控制 open 属性,不能只靠 HTML。
常见错误是写一堆并列的 <details>,结果用户能随意点开任意一步,顺序引导失效。真正可用的分步引导,必须让前一步完成(比如点击“继续”)后,才让下一步可交互或自动展开。
- 每步用一个
<details>包裹,但初始状态统一设为open=false - 第一步手动加
open属性,或用 JS 在加载时打开 - 每个步骤末尾放一个
<button>,点击后用 JS 设置下一项的open = true并滚动到它 - 禁用后续步骤的
<summary>点击(比如加pointer-events: none),避免跳步
summary 里别放复杂交互元素
<summary> 是触发区域,浏览器对它的内容支持有限。如果在里面塞 <button>、<input> 或监听 click 的 <span>,在 Safari 和部分旧版 Chrome 中可能无法响应,或者触发两次展开/收起。
- 把操作按钮放在
<details>内部、<summary>外面(即<details><summary>…</summary><div><button>下一步</button></div></details>) - 避免给
<summary>加onclick或addEventListener('click') - 如果需要“展开即聚焦输入框”,要在
toggle事件后延迟执行focus(),否则 Firefox 下会失效
用 toggle 事件监听展开/收起状态变化
不能只靠 click 或 change 监听 <details>,因为它的状态切换是通过 toggle 事件通知的——这是唯一可靠的方式。
立即学习“前端免费学习笔记(深入)”;
document.querySelectorAll('details').forEach(d => {
d.addEventListener('toggle', () => {
if (d.open) {
console.log('第', Array.from(d.parentElement.children).indexOf(d) + 1, '步已展开');
// 这里可以发埋点、校验上一步输入、滚动到视口等
}
});
});
-
toggle事件在用户点击<summary>时触发,也适用于 JS 修改open属性时(只要不是初始化赋值) - 不要在
toggle里直接改同一个<details>的open,否则可能引发循环 - 移动端 Safari 对
toggle的触发有时序问题,建议加requestAnimationFrame延迟读取d.open
兼容性与无障碍要注意 summary 的语义
<summary> 默认被屏幕阅读器识别为“可展开控件”,但如果你隐藏了它(比如用 CSS display: none),整个 <details> 就失去语义,键盘用户无法用空格/回车触发。也不能用 aria-hidden="true" 掩盖它。
- 保持
<summary>可见且可聚焦;如需视觉隐藏,用position: absolute; clip: rect(1px,1px,1px,1px) - 每步的
<summary>文本要明确,比如写“步骤 2:填写邮箱地址”,而不是“下一步” - Chrome 115+ 支持
details[open]:has(> summary:focus)这类选择器,但 Safari 完全不支持:has(),做样式联动时得用 JS 切 class
最麻烦的其实是滚动衔接和焦点管理——用户点“下一步”后,新展开的内容可能被顶部导航栏遮挡,或者键盘焦点没落到预期元素上。这些细节不处理,分步引导就只是个能点开的列表而已。



















