弹窗中禁用 ,因其在 fixed/transform 容器中事件失效、图标错位、状态不同步;应改用 max-height 过渡+overflow: hidden 方案,并严格处理焦点、aria-expanded 和父容器 CSS 陷阱。

弹窗里用 <details></details> 会失效,别硬套
弹窗(比如 modal 或 dialog)本质是脱离常规文档流的浮层,而 <details></details> 在部分浏览器(尤其是 Safari ≤15.4 和旧版 Edge)中,一旦被包裹在 position: fixed 或 transform 容器里,summary 点击可能无响应或 toggle 事件不触发。这不是你代码写错了,是渲染层限制。
-
<details></details>必须是正常文档流中的直系子元素才能可靠工作;弹窗常带transform: translate()或will-change,会干扰其内部事件捕获 - 即使能点开,原生箭头图标在弹窗内缩放后常错位,
summary::marker在 Safari 中基本不可控 - 弹窗内容通常需动态加载、高度不确定,
<details></details>的open属性无法响应 JS 插入后的重绘,容易状态不同步
用 max-height + overflow: hidden 是最稳的方案
这是目前在弹窗中实现平滑折叠展开的通用解法,不依赖浏览器原生行为,可控性强,兼容 IE11+(加前缀即可)。
- 不要设
height: auto过渡——CSS 根本不支持,只会跳变 - 把目标内容区的
max-height从0过渡到一个“足够但不过大”的值,例如max-height: 300px;收起时再回设为0 - 必须配
overflow: hidden,否则内容会溢出并撑高容器 - 如果弹窗内容含图片或字体加载后重排,首次展开前先调用
offsetHeight强制重排,再读取scrollHeight动态赋值给max-height,避免截断
点击区域和焦点管理比动画更重要
弹窗里的折叠项不是普通页面区块:用户可能用键盘导航、屏幕阅读器聚焦,或在小屏上误触。忽略这点,动画再顺也没用。
- 触发按钮必须有
role="button"和aria-expanded,且值要随状态实时更新,不能只靠 class 名判断 - 展开后,若内容区可滚动,应自动
focus()到第一个可交互子元素(如输入框、链接),否则键盘用户卡在空白处 - 避免在弹窗内监听
click到summary——它绕过原生toggle事件,键盘按空格/回车不会触发,且aria-expanded不同步 - 正确做法是监听弹窗内
<details></details>的toggle事件,或对自定义折叠区用addEventListener('click', ...)并手动管理aria-expanded
浮层布局本身就在破坏折叠逻辑
很多折叠失效问题,根源不在折叠代码,而在弹窗容器的 CSS 设置。常见踩坑点:
立即学习“前端免费学习笔记(深入)”;
- 父级弹窗用了
transform: scale(0.95)或filter: blur(1px)—— 这类合成层会让子元素事件区域偏移,summary看似在那儿,实际点击坐标没对上 - 弹窗设置了
pointer-events: none再局部开启(比如只给按钮设pointer-events: auto),但忘了给summary单独开权限 - 用了
dialog元素却没调用showModal(),导致其内部<details></details>失去模态上下文,事件冒泡异常 - 绝对定位的弹窗未设
position: relative父容器,导致折叠内容计算offsetTop错乱,影响自动滚动定位



















