summary必须是details的直接且首个子元素,否则safari等浏览器会忽略交互逻辑;错误示例包括中间插入空格、换行或其它标签;正确写法为标题内容。

为什么放错位置就点不动
浏览器只把 <summary></summary> 当作触发器,前提是它必须是 <details></details> 的**直接且首个子元素**。中间插空格、换行、<div> 或其他标签,都会让语义断裂,Safari 和旧版 Chrome 会直接忽略交互逻辑。
<ul>
<li>✅ 正确:<code><details><summary>标题</summary><p>内容</p></details>
<details><div><summary>标题</summary></div>
<p>内容</p></details>(<summary></summary> 不再是直接子元素)<details><p>说明文字</p>
<summary>标题</summary></details>(<summary></summary> 不是第一个子元素)服务端模板或 JSX 中容易因格式化自动插入换行/空格节点,建议压缩 HTML 输出,或手动写成单行结构。
summary::marker 为什么失效,怎么安全自定义箭头
summary::marker 在 Safari 全系和部分旧版 Chrome 中支持极差,甚至完全不渲染。强行依赖它会导致双箭头、无图标或点击区域消失。
- 先用
summary { list-style: none; }清除原生指示符 - 再用
summary::before { content: "▶"; margin-right: 4px; }插入自定义图标 - 展开状态靠
details[open] summary::before { content: "▼"; }切换 - 千万别用
display: none隐藏::marker——某些浏览器会连带禁用整个点击热区
Chrome 和 Firefox 对 ::marker 支持正在收敛,但生产环境仍建议以 ::before 为主、::marker 为辅。
加过渡动画时 max-height 总是裁剪或留白
<details></details> 展开是布尔切换,没有内置动画。想加高度过渡,不能直接对 <details></details> 或 <summary></summary> 做 height 过渡(height: auto 不可过渡),而要用 max-height + 容器包裹。
- 必须给内容包一层
<div class="details-content">,而不是直接放 <code><p></p>或<ul></ul> - 初始状态:
.details-content { max-height: 0; overflow: hidden; transition: max-height 0.3s ease; } - 展开状态:
details[open] .details-content { max-height: 300px; }(值需略大于内容实际高度) - 不要用
opacity或scaleY替代——它们无法解决内容溢出或布局抖动问题 - 应监听
toggle事件而非click,因为它是唯一可靠反映状态变更的钩子 - 避免在事件中立即读取
details.open—— Safari 存在微小渲染延迟,建议加requestAnimationFrame后再读 - 若需强制同步状态,优先用
details.toggleAttribute('open'),比赋值更稳定 - 服务端渲染时,初始状态务必靠 HTML 属性控制(
<details open></details>),别指望 JS 补救
这个 300px 不是魔法数字,它得比你最长内容的实际高度略大;设小了会裁剪,设太大则收起时留白明显。
Safari ≤15.4 中 JS 控制 open 属性为何无效
在 Safari ≤15.4 中,通过 JavaScript 设置 details.open = true 或调用 details.setAttribute('open', '') 可能无效:DOM 上已标记 open,但视觉仍收起。
真正容易被忽略的是:这个 bug 不报错、不警告,只是“看起来没反应”——排查时容易绕进 CSS 或事件绑定里打转。











