Yevhen Klymentiev
dark
light
console
darkness
y.klymentiev@gmail.com
Reusable Snippets|Practical utility code for everyday use — custom-built and ready to share

isInViewport

Checks if a DOM element is in the viewport.

TypeScript
Copied!
1/**
2 * Checks if a DOM element is in the viewport.
3 *
4 * @param el - The DOM element to check.
5 * @param partiallyVisible - If true, returns true if any part is visible.
6 * @returns True if the element is in the viewport.
7 */
8export function isInViewport(el: Element, partiallyVisible = true): boolean {
9  const rect = el.getBoundingClientRect();
10
11  if (partiallyVisible) {
12    return (
13      rect.bottom > 0 &&
14      rect.right > 0 &&
15      rect.top < window.innerHeight &&
16      rect.left < window.innerWidth
17    );
18  } else {
19    return (
20      rect.top >= 0 &&
21      rect.left >= 0 &&
22      rect.bottom <= window.innerHeight &&
23      rect.right <= window.innerWidth
24    );
25  }
26}
  • Supports Partial and Full Visibility Checks

    The partiallyVisible flag allows flexible usage depending on whether any or all of the element needs to be in view.

  • No External Dependencies

    Uses native DOM APIs like getBoundingClientRect, keeping the utility lightweight and portable.

  • High Performance

    Avoids complex intersection observers or polling, making it suitable for simple and fast viewport checks.

  • Versatile for Layout Decisions

    Provides foundational logic for lazy loading, animations, and scroll-triggered interactions.

Tests | Examples

TypeScript
Copied!
1function createElementWithRect(rect: Partial<DOMRect>): Element {
2  return {
3    getBoundingClientRect: () =>
4      ({
5        top: rect.top ?? 0,
6        bottom: rect.bottom ?? 0,
7        left: rect.left ?? 0,
8        right: rect.right ?? 0,
9      } as DOMRect),
10  } as unknown as Element;
11}
12
13Object.defineProperty(window, 'innerWidth', { value: 1024 });
14Object.defineProperty(window, 'innerHeight', { value: 768 });
15
16test('returns true if element is fully visible', () => {
17  const el = createElementWithRect({
18    top: 100,
19    bottom: 200,
20    left: 100,
21    right: 200,
22  });
23  expect(isInViewport(el, false)).toBe(true);
24});
25
26test('returns false if element is outside viewport', () => {
27  const el = createElementWithRect({
28    top: 800,
29    bottom: 900,
30    left: 100,
31    right: 200,
32  });
33  expect(isInViewport(el)).toBe(false);
34});
35
36test('returns true if element is partially visible', () => {
37  const el = createElementWithRect({
38    top: -50,
39    bottom: 50,
40    left: 100,
41    right: 200,
42  });
43  expect(isInViewport(el)).toBe(true);
44});
45
46test('returns false if element is not even partially visible', () => {
47  const el = createElementWithRect({
48    top: -200,
49    bottom: -100,
50    left: 100,
51    right: 200,
52  });
53  expect(isInViewport(el)).toBe(false);
54});

Common Use Cases

  • Lazy Loading Images or Components

    Trigger loading when a component enters the viewport to optimize performance and reduce initial load time.

  • Scroll-Triggered Animations

    Apply animations or transitions only when the element is visible to the user.

  • Infinite Scrolling

    Detect when the user has reached the end of a list or section to load more content.

  • Sticky Headers or UI Visibility

    Determine if a section is currently visible to toggle sticky headers or navigation indicators.

  • Accessibility or Focus Management

    Ensure key content is within view before shifting focus or reading content aloud.

Codebase: Utilities -> Browser & DOM -> isInViewport | Yevhen Klymentiev