scroll-snap-type 必须写在显式可滚动容器上而非 body/html;正确做法是新建包裹层并满足 height/min-height、overflow-y: scroll 和 scroll-snap-type 三条件,section 需设固定高度与 scroll-snap-align: start,iOS Safari 中 mandatory 易失效需降级或 JS 补齐。

scroll-snap-type 必须写在显式可滚动的容器上,不能直接写 body
直接给 body 或 html 加 scroll-snap-type: y mandatory 几乎总是失效。原因很实在:浏览器默认把页面滚动行为交给 html 元素处理,但它通常没有溢出内容(overflow-y 不触发),导致 snap 根本不计算。
正确做法是新建一个包裹层,比如 <div class="scroll-container">,并确保它满足三个硬性条件:
-
height: 100vh或更稳妥的min-height: 100dvh(iOS/Android 地址栏收放时不会跳变) -
overflow-y: scroll(必须是scroll或auto,hidden不行) scroll-snap-type: y mandatory
同时别忘了重置根元素样式:html, body { margin: 0; padding: 0; height: 100%; },否则外边距会干扰容器尺寸。
每个 section 必须设固定高度 + scroll-snap-align: start
只写 scroll-snap-align: start 不够,浏览器需要知道“停在哪”。如果 section 高度被 flex: 1、height: 100% 或内容撑开,Safari 和 Firefox 就可能忽略吸附,或停在错误位置。
立即学习“前端免费学习笔记(深入)”;
必须显式设置:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
-
height: 100vh(兼容性最广)或min-height: 100dvh(推荐新项目) -
scroll-snap-align: start(center在全屏场景下 Safari 支持不稳定) - 禁用
margin-top/margin-bottom——它会改变offsetTop,让视觉停靠点偏移
文字垂直居中别用 padding-top 模拟,改用 display: flex; align-items: center;,避免干扰 snap 基准线。
iOS Safari 上 mandatory 模式容易失效?这是设计使然
Safari 对 scroll-snap-type: y mandatory 的判定比 Chrome 严格得多:它要求每个 section 必须有“不可压缩的高度边界”。常见触发失效的点:
-
section内用了transform或will-change(会破坏 snap 计算) - 父容器用了
display: flex或grid布局(可能隐式拉伸子项) - 写了
scroll-snap-align: center却没配足够的padding或margin来提供对齐空间
临时绕过方式:降级为 scroll-snap-type: y proximity(吸附感弱但更稳),或加一行 JS 强制对齐:section.scrollIntoView({ block: 'start', behavior: 'smooth' }),注意仅在用户手势后调用才生效。
键盘和触控板默认不支持整页切换
scroll-snap 是纯滚动行为控制,不接管键盘事件。按空格键、方向键、PageDown 默认还是像素级滚动,不会切一整页。
要补上这个缺口,得监听 keydown 并手动干预:
- 过滤
ArrowDown、ArrowUp、(空格)、PageDown、PageUp - 调用
event.preventDefault()阻止默认行为 - 找到当前可见
section(可用IntersectionObserver或简单查window.scrollY+offsetTop) - 调用目标
section.scrollIntoView({ block: 'start', behavior: 'smooth' })
注意:Safari 下非用户手势触发的 behavior: 'smooth' 可能被静默降级为 instant,所以最好在 event.isTrusted === true 时才启用 smooth。


















