document.querySelectorAll匹配同类元素失效:嵌套层级不同致判断不生效
问题根因
- 代码中混用了两种元素位置计算逻辑,导致判断条件不匹配:
- 你代码开头自行计算的
offsetTop变量,是通过window.scrollY + scrollfade.getBoundingClientRect().top得到的,是元素相对于整个文档顶部的绝对距离 - 但if判断中使用的
scrollfade.offsetTop是DOM原生属性,它的取值是相对于元素最近的position不为static的父级元素的顶部距离,不是全局文档的距离
- 你代码开头自行计算的
- 当
.scrollfade在第二层时,若父元素无自定义定位,offsetTop刚好等同于相对于文档的距离,判断可以生效;当放到第三层时,如果第二层父元素设置了定位(比如常见的position: relative),原生offsetTop就变成了相对于第二层父元素的距离,和滚动判断的基准逻辑完全不匹配,因此无法触发判断。
修复方案
直接将判断条件里的scrollfade.offsetTop替换为你预先计算好的全局相对距离offsetTop即可,修正后代码如下:
window.addEventListener("scroll", function() { var scrollFadeClass = document.querySelectorAll(".scrollfade"); scrollFadeClass.forEach((scrollfade) => { // 该值为元素相对于文档顶部的绝对距离 var offsetTop = window.scrollY + scrollfade.getBoundingClientRect().top; var scrollTop = window.scrollY; // 替换判断条件里的属性为上面计算的offsetTop if (scrollTop + (window.innerHeight / 2.5) > offsetTop) { scrollfade.classList.add("complete"); }; }); });
可选优化
滚动事件触发频率非常高,建议添加节流逻辑减少不必要的计算,提升页面性能,示例如下:
// 节流函数,200ms最多触发一次 let scrollTimer = null; window.addEventListener("scroll", function() { if(scrollTimer) return; scrollTimer = setTimeout(() => { var scrollFadeClass = document.querySelectorAll(".scrollfade"); scrollFadeClass.forEach((scrollfade) => { var offsetTop = window.scrollY + scrollfade.getBoundingClientRect().top; var scrollTop = window.scrollY; if (scrollTop + (window.innerHeight / 2.5) > offsetTop) { scrollfade.classList.add("complete"); }; }); scrollTimer = null; }, 200) });
内容的提问来源于stack exchange,提问作者daaaaaaaaaaaaaryl
相关产品推荐
相关产品推荐

