弹窗内容过长时,必须为内部内容容器设 max-height 和 overflow-y: auto,而非直接作用于 .modal;因 .modal 多为 fixed/flex 容器,无高度限制则无法触发滚动,且需防 ios 穿透、正确绑定 js 滚动操作。

弹窗里内容过长时,必须让弹窗内部区域滚动,而不是拖动整个页面——关键不是给弹窗加 overflow,而是给它里面那个「真正装内容的容器」设高度和滚动行为。
为什么直接给 .modal 加 overflow-y: auto 没用
因为 .modal 通常是 position: fixed 或 display: flex 容器,它本身不承载内容流,也不构成滚动上下文。浏览器只对有明确高度限制、且内容实际溢出的块级元素启用滚动机制。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
-
.modal没设max-height或height→ 即使写了overflow-y: auto,scrollHeight和clientHeight相等,根本滚不起来 - 子元素用了
display: contents或visibility: hidden→ 滚动高度计算异常,scrollTop始终为 0 - 父级或祖先加了
transform/will-change→ iOS Safari 可能跳过滚动事件派发
必须套一层可滚动的 <div> 并设样式<p>把实际内容(比如长列表、表单字段、日志文本)包进一个独立 <code><div class="modal-content">,所有滚动相关样式都落在它身上:<ul>
<li>必须设 <code>max-height: 70vh(不能只写 100% 或 auto)
overflow-y: auto(scroll 强制显示滚动条,适合 Safari 兜底)display: flex,这个 <div> 要加 <code>min-height: 0,否则子元素可能撑高导致 overflow 失效overscroll-behavior: contain 防穿透——但只对这层生效,不是弹窗外壳JS 控制滚动位置要绑定到内容容器,不是弹窗本身
想点击按钮回顶、或滚动到底部,操作目标必须是那个带 overflow-y: auto 的 <div>:<ul>
<li>用 <code>container.scrollTo({ top: 0, behavior: 'smooth' }),别调 window.scrollTo()
container 上:container.addEventListener('scroll', handler)
container.scrollTop >= container.scrollHeight - container.clientHeight - 0.5(用小数边界,防 subpixel 误判)requestAnimationFrame 包一层再设 scrollTop
iOS Safari 必须 JS + CSS 双保险防穿透
哪怕 CSS 全写对,在 iOS Safari 真机上仍可能底层滚动——因为它的 overscroll 行为对 transform 包裹、第三方 UI 框架封装层敏感。
- 弹窗打开时:
document.body.style.overflow = 'hidden',同时缓存window.scrollY - 关闭时还原:
window.scrollTo(0, savedScrollY) - 不要在遮罩层上无差别
touchmove.preventDefault()——会封死弹窗内自己的可滚动区域 - 如果弹窗内有允许滚动的区域(如
.scrollable-area),遮罩的touchmovehandler 要用e.target.closest('.scrollable-area')判断是否放行
最容易被忽略的是:滚动容器的高度是否真的被约束住了。DevTools 里看 computed height,如果不是你写的 max-height 值,说明子元素脱离文档流(比如用了 position: absolute 或 float),滚动上下文就断了。










