JavaScript实现滚动时根据特定div切换固定Header类名
问题修复方案
原代码存在几个关键问题导致功能失效,逐一解决后即可实现需求:
1. 选择器不匹配
- JS里用
.js-header选择header,但HTML中header只有site-header类,需给header添加js-header类; - JS里查找
.has-dark-theme元素,但HTML中深色区块的类是is-dark,需统一选择器。
2. 滚动事件重复绑定
原代码在sections.forEach内部绑定scroll事件,会给每个深色区块都绑定一次滚动监听,导致逻辑冲突。应该只绑定一次scroll事件,在事件内部遍历所有深色区块判断位置。
3. 位置判断逻辑错误
固定定位的header的offsetTop始终是0,不能用来判断滚动位置。应该用window.scrollY(当前滚动距离)加上header的高度,来判断header是否处于深色区块上方。
修正后的完整代码
HTML
<header class="site-header js-header"></header> <div class="section is-dark"></div> <div class="section"></div> <div class="section is-dark"></div> <div class="section is-dark"></div> <div class="section"></div> <div class="section"></div>
CSS
.site-header { position: fixed; width: 100%; height: 3em; top: 0; left: 0; color: black; /* 加背景方便观察效果 */ background-color: rgba(255,255,255,0.9); } .site-header.is-white { color: white; background-color: rgba(0,0,0,0.9); } .section { width: 100%; height: 100vh; background-color: white; } .section.is-dark { background-color: #222; }
JS
const header = document.querySelector(".js-header"); const sections = document.querySelectorAll(".is-dark"); // 只绑定一次滚动事件 window.addEventListener('scroll', () => { let shouldBeWhite = false; const headerHeight = header.offsetHeight; // 当前滚动距离 + header高度 = header底部的位置 const headerBottom = window.scrollY + headerHeight; sections.forEach(section => { const sectionTop = section.offsetTop; const sectionBottom = sectionTop + section.offsetHeight; // 判断header是否覆盖在当前深色区块范围内 if (headerBottom > sectionTop && window.scrollY < sectionBottom) { shouldBeWhite = true; } }); // 根据结果切换类 shouldBeWhite ? header.classList.add('is-white') : header.classList.remove('is-white'); });
逻辑说明
- 每次滚动时,计算header底部的位置(滚动距离+header高度);
- 遍历所有深色区块,判断header是否覆盖在区块上方:只要有一个区块满足条件,就切换header为白色文字;
- 若没有任何深色区块在header下方,切换回黑色文字。
内容的提问来源于stack exchange,提问作者Mathieu Préaud
相关产品推荐
相关产品推荐

