原生全屏滚动页面结构的关键在于滚动容器必须显式可滚动且子项具备明确停靠锚点。需用包裹层(如.scroll-container)设height: 100vh、overflow-y: scroll、scroll-snap-type: y mandatory;每个section须设height: 100vh和scroll-snap-align: start,禁用margin分隔,并在移动端加overscroll-behavior-y: contain与touch-action: pan-y。

原生全屏滚动页面结构的关键不在“怎么堆 section”,而在于滚动容器是否真正可滚动、子项是否具备明确的停靠锚点。直接在 body 或 html 上写 scroll-snap-type 几乎总是失效的。
scroll-snap-type 必须作用于显式可滚动容器
浏览器只对“有溢出内容且设置了 overflow-y: scroll(或 auto)”的元素应用 scroll-snap-type。而默认情况下,body 的滚动由 html 承担,但 html 又常被视口撑满、无溢出,导致 snap 完全不触发。
- 正确做法:新建一个包裹所有
section的<div class="scroll-container">,并设 <code>height: 100vh; overflow-y: scroll; scroll-snap-type: y mandatory; - 必须确保该容器高度固定——不能用
min-height或靠内容撑开,否则滚动高度不可控,snap 失效 - 给
html, body加margin: 0; padding: 0; height: 100%;,防止外边距干扰容器尺寸计算 - 每个
section必须设height: 100vh(垂直)或width: 100vw(水平),min-height仅作容错,不能替代 - 必须配
scroll-snap-align: start(顶部对齐)或center(居中对齐);只写scroll-snap-align不加值无效 - 避免给
section设margin-top/margin-bottom,它会改变 offsetTop,导致视觉停靠位置偏移 - 在滚动容器上加
overscroll-behavior-y: contain,彻底禁用纵向回弹 - 横向滚动(如相册)必须加
touch-action: pan-x,否则 iOS 会默认锁死横向滑动 - 不要在滚动容器内监听
touchstart或touchmove,哪怕空回调也会触发 passive event warning,拖慢滚动帧率 - WebKit 内核:
.scroll-container::-webkit-scrollbar { display: none; } - Firefox:
.scroll-container { scrollbar-width: none; } - 防占位补丁(必要时):
.scroll-container { overflow-y: -webkit-scrollable-area; },仅 WebKit 支持
每个 section 必须显式声明尺寸与对齐方式
scroll-snap-align 不是“建议对齐”,而是“强制停靠点”。如果 section 高度不固定、被 flex/gird 拉伸、或依赖内容自适应,浏览器无法确定停在哪,就会跳过 snap 或错位停靠。
移动端必须处理 overscroll-behavior 和 touch-action
iOS Safari 默认开启弹性回弹(overscroll),滚动到底部时会拉出空白再回弹,不仅破坏沉浸感,还会让 window.scrollY 在回弹阶段返回异常值,干扰 JS 判断逻辑。
隐藏滚动条要分浏览器写死
Chrome/Edge/Safari 下,scroll-snap 容器的滚动条默认可见,且会占位——即使设了 display: none,仍可能造成内容轻微偏移。
最易被忽略的点是:scroll-snap 不是“自动适配”,它对容器尺寸、子项尺寸、溢出状态三者都极其敏感。少一个 height: 100vh,或多一个 margin,就足以让整个滚动吸附失效——它不会报错,只会静默退化为普通滚动。











