CSS 实现滚动吸附效果

发布于:2025-06-23 ⋅ 阅读:(17) ⋅ 点赞:(0)

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-marginscroll-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;
    }
    

注意事项

  1. 移动端优化

    • 添加 -webkit-overflow-scrolling: touch 改善iOS体验
    • 确保触摸滚动顺畅
  2. 可访问性

    • 考虑为偏好减少动画的用户提供替代方案
    @media (prefers-reduced-motion: reduce) {
      .container {
        scroll-snap-type: none;
      }
    }
    
  3. 性能

    • 避免在包含大量元素的容器上使用强制吸附(mandatory)
    • 复杂布局可能会影响滚动性能

滚动吸附是一种强大的CSS功能,可以创建专业级的滚动体验而无需JavaScript,特别适合移动端和触屏设备。


网站公告

今日签到

点亮在社区的每一天
去签到