判断元素在可视区域?用于滚动加载,数据埋点等

判断元素在可视区域的方法有三种:

  1. offsetTop, scrollTop
  2. getBoundingClientRect
  3. IntersectionObserver
js 复制代码
`getViewHeight`:获取视图窗口高度
const getViewHeight = window.innerHeight || // (IE9+)
                    document.documentElement.clientHeight || //(W3C 标准盒模型下)
                    document.body.clientHeight // (老IE)

一、offsetTop + scrollTop (传统方式)

offsetTop: 当前元素相对于其 offsetParent 元素的顶部内边距的距离 scrollTop: 元素的内容顶部到它的视口可见内容的顶部的距离

js 复制代码
const getOffsetTop = (el) => el.offsetTop
const getScrollTop = () => document.documentElement.scrollTop

在视图区域内: getViewHeight <= (getOffsetTop() - getScrollTop())

二、getBoundingClientRect ### (兼容性更好)

Element.getBoundingClientRect() 获取一个元素的 位置和尺寸信息,相对于浏览器视口(ViewPort)的位置。

js 复制代码
const rect = document.getElementById('myElement').getBoundingClientRect(); 

console.log(rect);
{
  top: 100,      // 元素上边到视口顶部的距离
  right: 300,    // 元素右边到视口右边的距离
  bottom: 200,   // 元素下边到视口底部的距离
  left: 50,      // 元素左边到视口左边的距离
  width: 250,    // 元素宽度(只读,现代浏览器支持)
  height: 100,   // 元素高度(只读,现代浏览器支持)
  x: 50,         // left 的别名
  y: 100         // top 的别名
}

在视图区域内: getViewHeight() >= rect.top

三、IntersectionObserver (性能更好)

IntersectionObserver 是现代 Web 开发中用于监听元素与视口(或祖先容器)交叉状态 的 API。异步执行的,不会频繁触发重排。

常用于实现:

  • 懒加载图片/内容
  • 无限滚动
  • 广告可见性统计
  • 动态加载组件等
js 复制代码
const observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) { // 元素进入视口
            console.log('元素已进入视口:', entry.target);
            observer.unobserve(entry.target); // 可选:只观察一次后取消监听
        }
    });
}, {
    root: null,                     // 监听相对于哪个容器,默认为浏览器视口
    rootMargin: '0px 0px 200px 0px' // 视口边缘偏移,距离底部200px就开始加载
    threshold: [0.1, 0.2]           // 分别触发回调,根据不同的 `intersectionRatio` 执行不同的逻辑
});

// 要监听的目标元素
const target = document.querySelector('#myElement');
observer.observe(target);

其他补充

1. content-visibility 和 contain-intrinsic-size

content-visibilityCSS 的一个新特性,属于 CSS Containment 模块的一部分。它允许浏览器跳过对某些元素的渲染工作(包括布局和绘制),直到它们进入视口或被主动触发渲染。

这个属性对于提升页面性能、实现"懒加载"效果,适合内容量大的页面(如长列表、文章流、卡片墙等)。

效果说明:

  1. 在视口内,渲染完整内容
  2. 不在视口内,跳过渲染,仅保留固定高度(由 contain-intrinsic-size 指定)
css 复制代码
.lazy-render {
  content-visibility: auto;
  contain-intrinsic-size: auto 100px; /* 告诉浏览器预留多少高度 */
}

2. 用 IntersectionObserver 实现图片懒加载

html 复制代码
<img data-src="image.jpg" alt="Lazy Image" class="lazy-img">
js 复制代码
const images = document.querySelectorAll('.lazy-img');

const imageObserver = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src;
            img.classList.add('loaded');
            observer.unobserve(img); // 加载完成后停止监听
        }
    });
}, {
    rootMargin: '0px',
    threshold: 0.01
});
images.forEach(img => imageObserver.observe(img));
相关推荐
好好研究22 分钟前
使用JavaScript实现轮播图的自动切换和左右箭头切换效果
开发语言·前端·javascript·css·html
程序视点4 小时前
IObit Uninstaller Pro专业卸载,免激活版本,卸载清理注册表,彻底告别软件残留
前端·windows·后端
前端程序媛-Tian5 小时前
【dropdown组件填坑指南】—怎么实现下拉框的位置计算
前端·javascript·vue
嘉琪0015 小时前
实现视频实时马赛克
linux·前端·javascript
烛阴5 小时前
Smoothstep
前端·webgl
若梦plus6 小时前
Eslint中微内核&插件化思想的应用
前端·eslint
爱分享的程序员6 小时前
前端面试专栏-前沿技术:30.跨端开发技术(React Native、Flutter)
前端·javascript·面试
超级土豆粉6 小时前
Taro 位置相关 API 介绍
前端·javascript·react.js·taro
若梦plus6 小时前
Webpack中微内核&插件化思想的应用
前端·webpack
若梦plus6 小时前
微内核&插件化设计思想
前端