CSS 滚动捕捉
学习scroll-snap · 难度:进阶 · +15XP
CSS 滚动捕捉 Scroll Snap
scroll-snap 系列属性可以在用户滚动结束后,让内容自动吸附到指定位置,实现类似轮播图、全屏滚动等效果,全程无需 JavaScript。
核心属性
| 属性 | 作用在 | 说明 |
|---|---|---|
scroll-snap-type | 滚动容器(父) | 定义滚动方向和吸附方式 |
scroll-snap-align | 子元素 | 定义吸附对齐位置 |
scroll-snap-stop | 子元素 | 是否强制停在当前元素 |
scroll-padding | 滚动容器 | 吸附偏移量(留出安全距离) |
scroll-margin | 子元素 | 子元素吸附外边距 |
scroll-snap-type
/* 水平 + 强制吸附 */
.container {
scroll-snap-type: x mandatory;
}
/* 垂直 + 靠近吸附 */
.container {
scroll-snap-type: y proximity;
}
/* 双向吸附 */
.container {
scroll-snap-type: both mandatory;
}
mandatory 强制吸附(滚动必定停在吸附点)vs proximity 靠近吸附(仅当接近吸附点时才吸附)。
scroll-snap-align
.section {
scroll-snap-align: start; /* 吸附到元素起始边 */
scroll-snap-align: center; /* 吸附到元素中心 */
scroll-snap-align: end; /* 吸附到元素结束边 */
}
全屏滚动示例
<div class="fullpage-scroll">
<section>第一页</section>
<section>第二页</section>
<section>第三页</section>
</div>
<style>
.fullpage-scroll {
height: 100vh;
overflow-y: scroll;
scroll-snap-type: y mandatory;
}
.fullpage-scroll section {
height: 100vh;
scroll-snap-align: start;
display: flex;
align-items: center;
justify-content: center;
font-size: 2em;
}
</style>
水平轮播(Carousel)
.carousel {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
gap: 16px;
padding: 10px;
scroll-padding: 10px;
}
.carousel-item {
flex: 0 0 80%;
scroll-snap-align: center;
border-radius: 12px;
overflow: hidden;
}
.carousel-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
scroll-padding 和 scroll-margin
用于处理吸顶导航栏遮挡的问题:
.scroll-container {
scroll-snap-type: y proximity;
scroll-padding-top: 60px; /* 留出 60px 给固定导航栏 */
}
/* 或在使用子元素上设置 */
.snap-child {
scroll-margin-top: 60px;
}
实际应用
- 产品展示轮播:水平滑动,每次展示一个产品卡片
- 全屏引导页:移动端全屏滚动引导(onboarding)
- 图库浏览:图片按网格滚动,吸附到网格位置
- 故事/快拍:类似 Instagram Stories 的横向滑动体验
- 时间轴滚动:纵向滚动时间轴,每次吸附到一个事件节点
兼容性和优雅降级
/* 提供回退方案 */
@supports (scroll-snap-type: x mandatory) {
.carousel {
scroll-snap-type: x mandatory;
}
}
/* 不支持时的回退 */
@supports not (scroll-snap-type: x mandatory) {
.carousel {
/* 使用传统的滚动指示器或 JS 方案 */
}
}
Scroll Snap 是 CSS 中最实用的新特性之一,它用几行代码就能实现之前需要大量 JavaScript 的吸附滚动效果,性能更好,代码更简洁。