和可原生实现无js折叠交互,但需修复点击区域异常、内容塌陷、状态样式及safari兼容性等问题。

<details></details> 和 <summary></summary> 能原生实现无 JS 的折叠交互,但默认样式丑、控制粒度粗,直接用在生产环境大概率要改。
为什么<summary></summary>的点击区域总是不听话
浏览器对 <summary></summary> 的可点击区域有隐式限制:只有文本内容和部分内边距生效,padding 超出一定范围(尤其上下)可能失效;若内部嵌套 <span></span> 或图标,还容易触发多次 toggle 事件(视觉上像点了两下)。
- 把交互区域显式撑开:给
<summary></summary>设display: block+ 合理padding,避免依赖默认行盒行为 - 禁用用户选中干扰:加
user-select: none,防止双击误选文字导致折叠状态异常 - 图标对齐别靠
vertical-align: middle硬调——它受父行高影响大,改用display: flex; align-items: center
<details></details> 展开后内容高度塌陷怎么办
展开时内容突然“跳动”,本质是 <details></details> 默认设了 display: block,但子元素若含浮动、绝对定位或未清除的 BFC,会导致父容器高度计算错误。
- 强制建立新 BFC:给
<details></details>加overflow: hidden或display: flow-root(后者更语义清晰) - 避免在
<summary></summary>后直接写文本——换行符会被渲染为空白,导致意外间隙;统一用<p></p>或<div> 包裹内容 <li>如果内容里有 <code><pre class="brush:php;toolbar:false;"></pre>或长单词,记得加word-break: break-word,否则可能撑破容器 - 展开时加边框/阴影:
details[open] { border-left: 3px solid #007bff; } - 折叠时隐藏箭头(默认三角):
summary::marker { content: ""; }(注意 Safari 目前不支持::marker,得用list-style: none+ 自定义::before图标) - 动画必须用
max-height+transition模拟,不能直接height: auto动画(CSS 不支持);设个足够大的max-height值(如500px),再配overflow: hidden
如何用 CSS 检测展开/折叠状态并定制样式
不能用 JS 就只能靠伪类:<details></details> 在展开时会匹配 :not([open]) 反向逻辑很绕,但这是唯一原生途径。
真正麻烦的是 Safari 对 ::marker 和 details[open] 的样式穿透支持不一致,比如 summary::marker 在展开后仍显示。这种细节没 JS 补位的话,得靠 @supports 分条件写样式,或者干脆放弃三角图标改用字体图标手动控制。











