全屏滑动吸附必须将scroll-snap-type: y mandatory写在独立容器上,该容器需同时满足height: 100vh、overflow-y: scroll、内容总高度大于视口,缺一不可;直接写在body或html上因ua样式干预被静默忽略。

全屏滑动吸附必须用 scroll-snap-type: y mandatory 写在独立容器上,且该容器要同时满足 height: 100vh、overflow-y: scroll、内容总高度 > 视口 —— 少一个条件,吸附就完全不触发。
为什么直接给 body 或 html 加 scroll-snap-type 没反应
浏览器对 body 和 html 的滚动行为有 UA 样式干预和系统级策略绕过,scroll-snap-type 在它们身上会被静默忽略。DevTools 里能看到声明,但 computed styles 中为空,就是这个原因。
- 必须用一个包裹的
<div class="scroll-container"> 作为滚动容器 <li>该容器不能是 <code>body的子元素再套一层 layout wrapper(比如.wrapper > .inner),scroll-snap-align只认它的**直接子元素** - 移动端真机测试时若 Timeline 面板不出现
ScrollStart/ScrollEnd,说明容器根本没被识别为可 snap 的滚动上下文 - 子项必须写
height: 100vh,不是min-height;超长内容需加overflow: hidden或内部滚动,否则吸附基准会下移 - 禁用
margin-bottom分隔子项——它会让可滚动距离 ≠ 视口高度,松手后卡在两页之间;改用padding-bottom或负外边距抵消 - 避免
transform、position: sticky等干扰盒模型边界的属性,它们会让scroll-snap-align失去锚点依据 - 横向轮播才用
touch-action: pan-x,别混用多值如pan-y pinch-zoom,部分 WebView 会因此冲突导致双指缩放失效或滑动卡顿 -
-webkit-overflow-scrolling: touch已废弃,现代 iOS 不仅不需要,留着还可能干扰原生滚动行为,建议删掉 - 如果页面有下拉刷新逻辑,注意
overscroll-behavior-y: contain可防止滚动穿透,但它对垂直全屏吸附非必需,优先保证touch-action正确
scroll-snap-align: start 为什么比 center 更稳
垂直全屏滚动中,scroll-snap-align: start 把每个子项的**上边缘**对齐到容器视口顶部,只要子项高度是 100vh,就能严丝合缝。而 center 要求容器与子项高度比精确为 1:1,稍有偏差(比如 iOS Safari 地址栏收缩导致视口高度变化)就会吸附偏移。
移动端必须加 touch-action: pan-y
iOS Safari 和 Android Chrome 120+ 默认拦截 touch 事件做手势优化,不显式放开 pan-y,滚动事件根本不会进入 scroll snap 引擎,表现为“能滑、不吸附、松手即停在任意位置”。
最容易被忽略的是子项高度一致性:哪怕只有一项用了 min-height 或漏了 box-sizing: border-box,Safari 就会在快速滑动后停在两页之间——这不是 bug,是 WebKit 对滚动惯性的主动妥协,调试时务必用真机反复验证每项的实际渲染高度。











