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

如何用JavaScript实现滚动吸附时背景色匹配对应Div颜色?

解决Scroll-Snap吸附时同步页面背景色的问题

核心方案

用原生Intersection Observer API监听滚动吸附的元素,当元素滚动到视口中心时,同步更新页面背景色。这个API无需依赖任何库,刚好适配你的需求,比用scrollY/offsetTop的方式更精准。

实现步骤

  1. 初始化时把每个.book的背景色存入自定义属性,方便后续直接获取
  2. 配置Intersection Observer,将观察区域定位到视口中心,确保只有元素吸附到中心时触发回调
  3. 监听元素交叉状态,触发时更新页面背景色

修改后的完整代码

HTML(无改动)

<div id="background" class="container">
    <header>
        <h2>BACKSTAGE TALKS</h2>
    </header>
    <div class="info">
        <p> Backstage Talks is a magazine <br>
            casual, but in depth dialogues <br>
            on design and business. Our decisions <br>
            shape and influence this complex <br>
            world—to have a chance to make the <br>
            right ones, we need to talk </p>
    </div>
    <div id="scroll-box" class="scroller">
        <div class="book" id="book_issue-1">1</div>
        <div class="book" id="book_issue-2">2</div>
        <div class="book" id="book_issue-3">3</div>
        <div class="book" id="book_issue-4">4</div>
        <div class="book" id="book_issue-5">5</div>
        <div class="book" id="book_issue-6">6</div>
    </div>

    <div class="links">
        <h2>info@backstagetalks.com</h2>
        <div class="issue-list">
            <p id="issue1"><a href="#book_issue-1">Issue #1</a></p>
            <p id="issue2"><a href="#book_issue-2">Issue #2</a></p>
            <p id="issue3"><a href="#book_issue-3">Issue #3</a></p>
            <p id="issue4"><a href="#book_issue-4">Issue #4</a></p>
            <p id="issue5"><a href="#book_issue-5">Issue #5</a></p>
            <p id="issue6"><a href="#book_issue-6">Issue #6</a></p>
        </div>
    </div>
</div>

CSS(无改动)

@import url('https://fonts.googleapis.com/css2?family=Bangers&family=Chivo+Mono:ital,wght@1,500&family=Hanalei+Fill&family=Fredoka+One&display=swap');

html, body{
    margin: 0;
    /* font-family: Arial, Helvetica, sans-serif; */
}
::-webkit-scrollbar {
    display: none;
}

header {
    padding: 0.7em 0 0 0 ;
    color: red;
    font-family: 'Bangers';
    font-size: 25px;
}

header h2 {
    margin: 0;
}

.container {
    height: 100vh;
    display: flex;
    justify-content: space-between;
    /* border: 2px solid brown; */
}

.scroller {
    max-height: 100vh;
    overflow: scroll;
    scroll-snap-type: y mandatory;
    margin: 0 auto;
    width: 100%;
    position: absolute;
    scroll-behavior: smooth;
    z-index: 1;
 
}

.book {
    /* border: 20px solid; */
    margin: 0 auto;
    /* padding: 1em; */
    width: 300px;
    scroll-snap-align: center;
    scroll-padding-top: 300px;
    display: flex;
    flex-flow: column;
    justify-content: center;
    text-align: center;
    font-size: 4em;
}


.links {
    display: flex;
    justify-content: space-between;
    flex-direction: column;
    /* padding: 0 1em; */
}

.links h2 {
    font-family: 'Fredoka One';
    font-weight: 100;
    padding: 0;
}

.issue-list {
    width: fit-content;
    margin-left: auto;
    font-family: 'Arial';
    font-size: 18px;
    z-index: 1;
}

.issue-list p{
    margin: 0;
}

.issue-list p a {
    cursor: pointer;
    text-decoration: none;
    color: black;
}

.info {
    position: absolute;
    bottom: 0;
    /* padding: 0 1em; */
}

.info p {
    font-size: 19px;
    font-weight: bold;
    font-family: 'Chivo Mono';
}

JavaScript(新增监听逻辑)

const gra = function (min, max) {
    return Math.random() * (max - min) + min;
};

const init = function () {
    let items = document.querySelectorAll(".scroller div");
    for (let i = 0; i < items.length; i++) {
        items[i].style.minHeight = gra(100, 100) + "vh";
        const randomColor = Math.floor(Math.random() * 16777215).toString(16);
        const colorHex = "#" + randomColor;
        items[i].style.backgroundColor = colorHex;
        // 把颜色存入自定义属性,避免后续格式转换
        items[i].dataset.color = colorHex;
    }

    // 初始化滚动吸附监听
    setupScrollSnapObserver();
};

const setupScrollSnapObserver = function() {
    const scrollContainer = document.getElementById('scroll-box');
    const books = document.querySelectorAll('.book');

    // 配置观察规则:根元素为滚动容器,观察区域缩至视口中线
    const observerOptions = {
        root: scrollContainer,
        rootMargin: "-50% 0px -50% 0px",
        threshold: 1.0
    };

    // 交叉状态变化时的回调
    const observerCallback = (entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                // 更新页面背景色为当前吸附元素的颜色
                document.getElementById('background').style.backgroundColor = entry.target.dataset.color;
            }
        });
    };

    // 创建Observer并监听所有.book元素
    const observer = new IntersectionObserver(observerCallback, observerOptions);
    books.forEach(book => observer.observe(book));
};

init();

关键细节说明

  • rootMargin: "-50% 0px -50% 0px":将观察区域限制在视口的水平中线位置,只有当元素中心与中线重合(即scroll-snap到中心)时,才会触发交叉状态
  • threshold: 1.0:确保元素完全进入观察区域时才触发回调,避免滚动过程中频繁切换颜色
  • dataset.color:提前存储hex格式的颜色,避免直接从style.backgroundColor获取到rgb格式的颜色,减少格式转换的麻烦

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 21:55:15