不用 JS,纯 CSS做一屏滚动:scroll-snap完整教程

更新日期: 2026-09-20 阅读: 17 标签: 滚动

很多企业官网、产品介绍页、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 和安卓真机上各试一遍,重点看地址栏收起时高度有没有跳,滚动是否顺滑。

本文内容仅供个人学习、研究或参考使用,不构成任何形式的决策建议、专业指导或法律依据。未经授权,禁止任何单位或个人以商业售卖、虚假宣传、侵权传播等非学习研究目的使用本文内容。如需分享或转载,请保留原文来源信息,不得篡改、删减内容或侵犯相关权益。感谢您的理解与支持!

相关推荐
js禁止页面滚动

js禁止页面滚动

发移动端页面的时候有一个很比较常见的需求,在出现弹窗时,禁止滑动弹窗后面的主体页面。如何实现呢,往下看

js如何实现滚动到一定位置将内容固定在页面顶部

window.onscroll为滚轮监听,document.body.scrollTop||document.documentElement.scrollTop 写两个是为了兼容不同浏览器。固定位置的top要设为负值,原因不明,若为0则会跟上方有空隙。左右位置虽然是0也要设,不然若为不是100%宽度的内容会出现左右跳动。

js 禁止/允许页面滚动

passive,设置该属性的目的主要是为了在阻止事件默认行为导致的卡顿。等待监听器的执行是耗时的,有些甚至耗时很明显,这样就会导致页面卡顿。即便监听器是个空函数,也会产生一定的卡顿,毕竟空函数的执行也会耗时

js实现返回顶部效果的方法总结

js实现返回顶部效果的方法总结

当页面特别长的时候,用户想回到页面顶部,必须得滚动好几次滚动键才能回到顶部,如果在页面右下角有个返回顶部的按钮,用户点击一下,就可以回到顶部,对于用户来说,是一个比较好的体验。

js+css 实现 滚动条滑动时显示,不滑动时隐藏

把原有的滚动条隐藏,创建个新的滚动条,并拓展其宽度,达到隐藏的效果,而判断滚动条是否滚动,保存原有的滚动条到顶部的距离,看是否发生改变,做出相应的判断。

使用elementUI滚动条之横向滚动

这里要简单的设置一下,将标签的height设为100%,读者查看效果的时候,会出现一个横向的滚动条,如果你不想要横向的滚动条,使用下面css属性设置就可以只显示竖向滚动条。

BetterScroll移动端滚动场景的应用

BetterScroll 是一款重点解决移动端各种滚动场景需求的开源插件,有下列功能支持滚动列表,下拉刷新,上拉刷新,轮播图,slider等功能。better-scroll通过使用惯性滚动、边界回弹、滚动条淡入淡出来确保滚动的流畅。

原生js获取浏览器获X轴,Y轴的滚动距离

在前端开发中,需要获取浏览器滚动距离的需求,这篇文章主要讲解如何使用原生Js兼容实现获取浏览器获X轴,Y轴的滚动距离。并延伸扩展下我们一些不知道的js知识,希望对你有所帮助。

CSS让页面平滑滚动

CSS让页面平滑滚动

在PC浏览器中,网页默认滚动是在<html>标签上的,移动端大多数在<body>标签上,业界浏览器的CSS reset都可以加上这么一条规则:凡是需要滚动的地方都加一句scroll-behavior:smooth就好了!

原生js判断加载更多事件,通过获取页面滚动距离、文档总高度、浏览器视口高度

原生js判断加载更多事件,通过获取页面滚动距离、文档总高度、浏览器视口高度

原生js获取滚动条在Y轴上的滚动距离、获取文档的总高度、获取浏览器视口的高度的方法实现,用于判断页面加载数据。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!