不用 JS,纯 CSS做一屏滚动:scroll-snap完整教程
很多企业官网、产品介绍页、H5 活动页都有一种效果:上下滑动时,页面一屏一屏切换,不会停在两屏中间。以前做这种效果,很多人会引入 fullpage.js。插件功能多,但文件也不小,配置还麻烦。
现在用 CSS 自带的 scroll-snap 就能做。不用 JavaScript,代码短,性能好,手机上也顺。下面直接给完整代码,再讲清楚每一行为什么要写。
完整代码,复制就能跑
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>纯 CSS 一屏滚动</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
height: 100%;
}
/* 不让 body 滚动,滚动交给 .box */
body {
overflow: hidden;
}
/* 滚动容器 */
.box {
width: 100%;
height: 100vh;
height: 100dvh; /* 移动端更准,不支持就回退到 100vh */
overflow-y: scroll;
scroll-snap-type: y mandatory;
-webkit-overflow-scrolling: touch; /* 老 iOS 惯性滚动 */
scrollbar-width: none; /* Firefox 隐藏滚动条 */
-ms-overflow-style: none; /* 旧 Edge / IE 隐藏滚动条 */
}
/* Chrome、Safari、Edge 隐藏滚动条 */
.box::-webkit-scrollbar {
display: none;
}
/* 每一屏 */
.page {
height: 100vh;
height: 100dvh;
scroll-snap-align: start;
scroll-snap-stop: always;
display: flex;
align-items: center;
justify-content: center;
font-size: 40px;
color: #fff;
}
.p1 {
background: #409eff;
}
.p2 {
background: #67c23a;
}
.p3 {
background: #e6a23c;
}
</style>
</head>
<body>
<div class="box">
<section class="page p1">第一屏</section>
<section class="page p2">第二屏</section>
<section class="page p3">第三屏</section>
</div>
</body>
</html>关键 CSS 就这几行
真正让页面“一屏一屏吸附”的,是下面三行:
.box {
scroll-snap-type: y mandatory;
}
.page {
scroll-snap-align: start;
scroll-snap-stop: always;
}1. scroll-snap-type: y mandatory
这行写在滚动容器上。y 表示垂直方向,mandatory 表示强制吸附。你滑动松手后,浏览器必须让某一屏对齐,不会停在两屏中间。
还有一个值叫 proximity,意思是“靠近了才吸附”。它更温和,适合内容不全是整屏的页面。企业站做全屏分页,一般用 mandatory。
2. scroll-snap-align: start
这行写在每一屏上。start 表示这一屏的顶部,对齐滚动容器的顶部。这样每次切换,新的一屏都会从顶部开始显示。
也可以写 center 或 end,但全屏页面通常用 start 最自然。
3. scroll-snap-stop: always
这行也写在每一屏上。作用是快速滑动时,尽量不跳过中间那一屏。比如从第一屏猛滑一下,不要直接飞到第三屏,而是先停在第二屏。
要注意,这个属性不是所有浏览器都完全一样。它能帮上忙,但不能把它当成 100% 的拦截。真正要限制跳屏,还要看设备和浏览器。
其他代码在干什么
body { overflow: hidden; } 是为了不让整个页面滚动。滚动只发生在 .box 里面。
.box 必须有固定高度,还要有 overflow-y: scroll。没有高度,scroll-snap 不会按你想的方式工作。
height: 100vh 是老写法。手机浏览器地址栏会收起、展开,100vh 有时候会偏高或偏低。所以再加一行 height: 100dvh。支持 dvh 的浏览器会用动态视口高度,不支持的会自动忽略,继续用 100vh。
-webkit-overflow-scrolling: touch 是给老 iOS 设备用的。新版本 iOS 已经默认有惯性滚动,这行可留可删。留着不影响新设备,主要是兼容老机器。
隐藏滚动条的代码有三段:scrollbar-width: none 管 Firefox,-ms-overflow-style: none 管旧 Edge 和 IE,::-webkit-scrollbar 管 Chrome、Safari、Edge。隐藏后页面更干净,但用户可能不知道还能滑。企业站可以加箭头或小圆点提示。
常见问题
为什么我的页面不吸附?
先看 scroll-snap-type 是不是写在滚动容器上,不是写在 body 上。再看容器有没有固定高度和 overflow-y: scroll。最后看每一屏有没有写 scroll-snap-align。这三个地方缺一个,效果就可能出不来。
为什么快速滑动会跳过一屏?
加上 scroll-snap-stop: always。但它不是万能,部分浏览器支持有限。如果必须严格一屏一屏,还是得用 JavaScript 配合。
内容超过一屏怎么办?
mandatory 强制吸附,适合每屏内容刚好一屏的页面。如果某一屏内容很长,强制吸附可能让你看不到底部内容。这种页面建议改成 proximity,或者让每屏内部自己滚动。
手机端高度不对怎么办?
优先用 100dvh,保留 100vh 做回退。也可以配合 viewport-fit=cover,让页面在刘海屏上显示更完整。
键盘用户能滚吗?
可以给 .box 加 tabindex="0",让它能获得焦点。然后用键盘上下键滚动。注意加焦点样式,别让用户不知道焦点在哪。
和 fullpage.js 比,选哪个
fullpage.js 功能多,有导航、回调、动画、循环滚动,适合复杂项目。缺点是体积大,配置多,定制有时麻烦。
scroll-snap 是浏览器原生能力。代码少,加载快,性能好。适合企业站首页、产品介绍 H5、活动页、简历页、移动端引导页。不适合长文章、表格、需要连续滚动的页面。
简单说:只要你的需求是“整屏分页,每屏内容不多”,就用 scroll-snap。需要复杂交互和完整控制,再考虑 fullpage.js。
最后提醒
纯 CSS 一屏滚动不难,关键是理解滚动容器和每一屏的关系。容器负责吸附,每一屏负责对齐。把高度、溢出、吸附这三件事写对,效果就出来了。
代码可以直接复制,改一改背景色和文字就能用。上线前记得在 iOS 和安卓真机上各试一遍,重点看地址栏收起时高度有没有跳,滚动是否顺滑。
本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!