You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何同时实现Scroll-Snap滚动吸附与背景色过渡效果?

解决Scroll-Snap与背景色过渡共存的问题

问题核心很明确:当给main设置height:100vh时,滚动条属于main元素而非window,但你原来的代码监听的是window的滚动事件,导致背景色切换逻辑完全不触发;去掉height后,滚动条回到window,背景色生效,但scroll-snap因为没有明确的滚动容器高度而失效。

修复方案

  1. 将滚动事件的监听对象从window改为main元素
  2. 调整滚动位置的计算逻辑,基于main的滚动状态而非window
  3. 保留main的height:100vh以维持scroll-snap的功能

修改后的完整代码

JavaScript

const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
        if (entry.isIntersecting) {
            entry.target.classList.add('show');
        } else {
            entry.target.classList.remove('show');
        }
    });
});

// 监听main元素的滚动事件,而非window
$('main').scroll(function() {
    // selectors
    var $main = $(this),
        $body = $('body'),
        $panel = $('.panel');
    
    // 基于main的滚动位置和自身高度计算触发点
    var scroll = $main.scrollTop() + ($main.height() / 3);
   
    $panel.each(function () {
      var $this = $(this);
      
      if ($this.position().top <= scroll && $this.position().top + $this.height() > scroll) {
        $body.removeClass(function (index, css) {
          return (css.match (/(^|\s)color-\S+/g) || []).join(' ');
        });
        $body.addClass('color-' + $(this).data('color'));
      }
    });    
}).scroll();

const hiddenElements = document.querySelectorAll('.hidden');
hiddenElements.forEach((el) => observer.observe(el));

CSS(保留原有核心配置)

body {
    margin: 0;
    padding: 0;
    font-family: sans-serif;
    background-color: rgb(36, 164, 138);
    transition: background-color 1s ease;
}

div {
    place-items: center;
    align-content: center;
    min-height: 100vh;
    color: white;
    position: relative;
    scroll-snap-align: start;
}

.panel {
    min-height: 100vh;
    display: flex;
    justify-content: space-around;
    align-items: center;
    font-family: sans-serif;
}

main {
    scroll-snap-type: y mandatory;
    overflow-y: scroll;
    height: 100vh; /* 必须保留,保证scroll-snap生效 */
}

.color-green {
    background-color: rgb(36, 164, 138);
}
.color-red {
    background-color: rgb(211, 79, 79);
}
.color-blue {
    background-color: rgb(67, 91, 175);
}
.color-salmon {
    background-color: lightsalmon;
}

.hidden {
    opacity: 0;
    filter: blur(5px);
    transform: translateX(-100%);
    transition: all 1s;
}

.show {
    opacity: 1;
    filter: blur(0);
    transform: translateX(0);
}

HTML(无需修改)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS SNAP EFFECT</title>
    <link rel="stylesheet" href="styles.css">
    <script defer src="app.js"></script>
    <script
        src="https://code.jquery.com/jquery-3.7.0.js"
        integrity="sha256-JlqSTELeR4TLqP0OG9dxM7yDPqX1ox/HfgiSLBj8+kM="
        crossorigin="anonymous">
    </script>
</head>
<body>
    <main>
            <div class="panel" data-color="green">
                    <h1 class="hidden">First</h1>
            </div>
            <div class="panel" data-color="red">
                    <h1 class="hidden">Second</h1>
            </div>
            <div class="panel" data-color="blue">
                    <h1 class="hidden">Third</h1>
            </div>        
            <div class="panel" data-color="salmon">
                    <h1 class="hidden">Last</h1>
            </div>
        
    </main>
</body>
</html>

修改后,scroll-snap会因为main的固定高度正常工作,背景色过渡也会因为监听了正确的滚动容器而触发,两者就能完美共存了。

内容的提问来源于stack exchange,提问作者Kyle Tobin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 00:28:11