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

原生JS实现section进入视口时为背景div增删类名问题求解

问题根源

你的判断逻辑存在缺陷:仅判断了滚动偏移量大于等于区块顶部就添加类名,没有同时校验是否还未滚动超出区块底部。这就导致所有你已经滚动经过的区块,对应的类名会被全部添加上,不会触发移除逻辑。


修复方案1:调整原有滚动监听逻辑

修改updateBg里的判断条件,仅当滚动位置处于当前区块的垂直范围内时才添加对应类名,否则直接移除,同时增加节流逻辑避免性能损耗:

const sections = document.querySelectorAll('section')
const bg = document.querySelector('div.background')

let isTicking = false
document.addEventListener('scroll', updateBg)

function updateBg() {
  if (!isTicking) {
    window.requestAnimationFrame(() => {
      const scrollY = window.pageYOffset
      sections.forEach((section) => {
        const sectionId = section.id
        const sectionTop = section.offsetTop
        const sectionBottom = sectionTop + section.offsetHeight
        // 仅当滚动位置落在当前区块范围内时加类,否则移除
        if (scrollY >= sectionTop && scrollY < sectionBottom) {
          bg.classList.add(sectionId)
        } else {
          bg.classList.remove(sectionId)
        }
      })
      isTicking = false
    })
    isTicking = true
  }
}
// 页面加载后先执行一次,避免初始状态类名异常
updateBg()

修复方案2:使用IntersectionObserver(更推荐)

用浏览器原生交叉监听API实现,不需要手动计算偏移量,性能更优:

const sections = document.querySelectorAll('section')
const bg = document.querySelector('div.background')

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    const sectionId = entry.target.id
    if (entry.isIntersecting) {
      bg.classList.add(sectionId)
    } else {
      bg.classList.remove(sectionId)
    }
  })
}, {
  // 阈值可自定义,0.5代表区块50%进入视口时触发状态切换
  threshold: 0.5
})

// 给所有section注册交叉监听
sections.forEach(section => observer.observe(section))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:06:03