initial version:

1
2
3
4
5
6
7
8
9
10
11
12
13
function isElementInView(element) {
if (!document) return false;
let viewHeight = document.documentElement.clientHeight; // 容器可见区域高度
let elemTopToViewTop = element.getBoundingClientRect().top; //元素顶端到可见区域顶端的距离
if (
elemTopToViewTop <= viewHeight &&
elemTopToViewTop >= 0 &&
elementHasHeight
) {
return true;
}
return false;
}

需要完善的点:

  • 判断 left 值
  • DOM 要有宽高
  • display: none & visibility: hidden 时应该是不可见的

final version:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
function isVisible(el) {
let { display, visibility } = getComputedStyle(el);
return display !== "none" && visibility !== "hidden";
}

function getWindowHeight() {
return window.innerHeight || document.documentElement.clientHeight;
}

function getWindowWidth() {
return window.innerWidth || document.documentElement.clientWidth;
}

function elHasWidthHeight(el) {
return el.clientHeight > 0 && el.clientWidth > 0;
}

function isPartOfElementInViewport(el) {
const rect = el.getBoundingClientRect();
const windowHeight = getWindowHeight();
const windowWidth = getWindowWidth();

const vertInView = rect.top <= windowHeight && rect.top + rect.height >= 0;
const horInView = rect.left <= windowWidth && rect.left + rect.width >= 0;

return vertInView && horInView && elHasWidthHeight(el) && isVisible(el);
}

function isElementAllInViewport(el) {
const rect = el.getBoundingClientRect();
const windowHeight = getWindowHeight();
const windowWidth = getWindowWidth();

return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= windowHeight &&
rect.right <= windowWidth &&
elHasWidthHeight(el) &&
isVisible(el)
);
}

DOM 元素各种高度值

clientHight

VISIBLE content (CSS height) & padding

offsetHeight

VISIBLE content (CSS height) & padding + border + scrollbar (no margin)

scrollHeight

ENTIRE content & padding (visible or not)

Reference