CSS 实现滚动吸附效果
滚动吸附(Scroll Snap)是一种 CSS 功能,可以让滚动操作结束时自动吸附到特定位置,非常适合创建分页滚动、轮播图或图片画廊等效果。
基本实现方法
1. 垂直滚动吸附
.container {
scroll-snap-type: y mandatory;
overflow-y: scroll;
height: 100vh;
}
.section {
scroll-snap-align: start;
height: 100vh;
}
2. 水平滚动吸附
.gallery {
scroll-snap-type: x mandatory;
overflow-x: scroll;
white-space: nowrap;
}
.slide {
scroll-snap-align: center;
display: inline-block;
width: 100vw;
height: 100vh;
}
详细属性说明
scroll-snap-type
- 容器属性
控制滚动吸附的行为:
.container {
/* 基本语法 */
scroll-snap-type: [x|y|both] [mandatory|proximity];
/* 示例 */
scroll-snap-type: y mandatory; /* 垂直方向强制吸附 */
scroll-snap-type: x proximity; /* 水平方向接近时吸附 */
}
轴方向:
x
- 水平滚动y
- 垂直滚动both
- 双向滚动
吸附强度:
mandatory
- 强制吸附,滚动停止时一定会吸附到最近的点proximity
- 接近吸附,只有滚动停止点接近吸附点时才会吸附
scroll-snap-align
- 子元素属性
定义元素的吸附对齐点:
.item {
/* 可以取以下值 */
scroll-snap-align: none; /* 默认值,不吸附 */
scroll-snap-align: start; /* 吸附到元素起始边缘 */
scroll-snap-align: end; /* 吸附到元素结束边缘 */
scroll-snap-align: center; /* 吸附到元素中心 */
}
完整示例
1. 全屏分页滚动效果
<!DOCTYPE html>
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
}
.scroll-container {
scroll-snap-type: y mandatory;
overflow-y: scroll;
height: 100vh;
scroll-behavior: smooth;
}
section {
scroll-snap-align: start;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
color: white;
}
#page1 { background: #FF5F6D; }
#page2 { background: #FFC371; }
#page3 { background: #4BC0C8; }
#page4 { background: #36D1DC; }
nav {
position: fixed;
top: 20px;
right: 20px;
z-index: 100;
}
nav a {
display: inline-block;
width: 12px;
height: 12px;
margin: 0 5px;
border-radius: 50%;
background: white;
opacity: 0.5;
transition: opacity 0.3s;
}
nav a:hover, nav a.active {
opacity: 1;
}
</style>
</head>
<body>
<nav>
<a href="#page1" class="active"></a>
<a href="#page2"></a>
<a href="#page3"></a>
<a href="#page4"></a>
</nav>
<div class="scroll-container">
<section id="page1">
<h1>第一页</h1>
</section>
<section id="page2">
<h1>第二页</h1>
</section>
<section id="page3">
<h1>第三页</h1>
</section>
<section id="page4">
<h1>第四页</h1>
</section>
</div>
<script>
// 更新导航点活动状态
const sections = document.querySelectorAll('section');
const navLinks = document.querySelectorAll('nav a');
function updateActiveNav() {
sections.forEach((section, index) => {
const rect = section.getBoundingClientRect();
if (rect.top >= 0 && rect.top <= window.innerHeight / 2) {
navLinks.forEach(link => link.classList.remove('active'));
navLinks[index].classList.add('active');
}
});
}
document.querySelector('.scroll-container').addEventListener('scroll', updateActiveNav);
</script>
</body>
</html>
2. 水平图片画廊
<!DOCTYPE html>
<html>
<head>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.gallery {
scroll-snap-type: x mandatory;
overflow-x: scroll;
white-space: nowrap;
height: 100vh;
-webkit-overflow-scrolling: touch; /* 改善iOS滚动体验 */
}
.slide {
scroll-snap-align: center;
display: inline-block;
width: 100vw;
height: 100vh;
position: relative;
}
.slide img {
width: 100%;
height: 100%;
object-fit: cover;
}
.caption {
position: absolute;
bottom: 20%;
left: 0;
right: 0;
text-align: center;
color: white;
font-size: 2rem;
text-shadow: 0 2px 4px rgba(0,0,0,0.5);
}
/* 隐藏滚动条 */
.gallery::-webkit-scrollbar {
display: none;
}
</style>
</head>
<body>
<div class="gallery">
<div class="slide">
<img src="https://source.unsplash.com/random/800x600?nature" alt="Nature">
<div class="caption">自然风光</div>
</div>
<div class="slide">
<img src="https://source.unsplash.com/random/800x600?city" alt="City">
<div class="caption">城市景观</div>
</div>
<div class="slide">
<img src="https://source.unsplash.com/random/800x600?animal" alt="Animal">
<div class="caption">野生动物</div>
</div>
<div class="slide">
<img src="https://source.unsplash.com/random/800x600?architecture" alt="Architecture">
<div class="caption">建筑艺术</div>
</div>
</div>
</body>
</html>
高级技巧
1. 边距控制 (scroll-margin
和 scroll-padding
)
/* 为吸附元素添加外边距 */
.item {
scroll-margin: 20px;
}
/* 为滚动容器添加内边距 */
.container {
scroll-padding: 50px 0 0 0; /* 顶部留出50px空间(适合固定导航栏) */
}
2. 双向滚动吸附
.grid-container {
scroll-snap-type: both mandatory;
overflow: scroll;
width: 100vw;
height: 100vh;
}
.grid-item {
scroll-snap-align: start;
width: 100vw;
height: 100vh;
}
3. 与平滑滚动结合
.container {
scroll-snap-type: y mandatory;
scroll-behavior: smooth;
overflow-y: scroll;
}
浏览器兼容性
- 现代浏览器(Chrome、Firefox、Safari、Edge)都支持
- 部分旧版本需要前缀:
.container { -webkit-scroll-snap-type: y mandatory; scroll-snap-type: y mandatory; } .item { -webkit-scroll-snap-align: start; scroll-snap-align: start; }
注意事项
移动端优化:
- 添加
-webkit-overflow-scrolling: touch
改善iOS体验 - 确保触摸滚动顺畅
- 添加
可访问性:
- 考虑为偏好减少动画的用户提供替代方案
@media (prefers-reduced-motion: reduce) { .container { scroll-snap-type: none; } }
性能:
- 避免在包含大量元素的容器上使用强制吸附(
mandatory
) - 复杂布局可能会影响滚动性能
- 避免在包含大量元素的容器上使用强制吸附(
滚动吸附是一种强大的CSS功能,可以创建专业级的滚动体验而无需JavaScript,特别适合移动端和触屏设备。