Web Development
JavaScript
Scrolling Function
User Interface
HTML Elements

How to check if element is visible after scrolling?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Checking whether an element is visible after scrolling is a common browser task. You might need it for lazy loading, analytics, sticky navigation, or animations that should start only when content enters the viewport. The important detail is that "visible" can mean either fully inside the viewport or only partially intersecting it.

Start by Defining Visibility

Before writing code, decide what your page actually needs. Some features only need partial visibility, such as loading an image when the top of a card appears. Other features need full visibility, such as measuring whether a consent banner is completely readable.

Those two definitions lead to different checks:

  • Partial visibility means any part of the element overlaps the viewport.
  • Full visibility means the entire rectangle fits inside the viewport.

That distinction prevents a lot of confusion when debugging scroll behavior.

A Direct Check with getBoundingClientRect

The lowest-friction approach is to read the element's rectangle relative to the viewport and compare it with the viewport size.

html
1<!doctype html>
2<html lang="en">
3  <head>
4    <meta charset="utf-8">
5    <title>Visibility Check</title>
6    <style>
7      body {
8        margin: 0;
9        font-family: sans-serif;
10      }
11
12      .spacer {
13        height: 900px;
14      }
15
16      .box {
17        margin: 0 auto;
18        width: 240px;
19        height: 120px;
20        background: #ffd166;
21        display: grid;
22        place-items: center;
23      }
24    </style>
25  </head>
26  <body>
27    <div class="spacer"></div>
28    <div id="target" class="box">Watch me</div>
29    <div class="spacer"></div>
30
31    <script>
32      function isPartiallyVisible(element) {
33        const rect = element.getBoundingClientRect();
34        const viewHeight = window.innerHeight || document.documentElement.clientHeight;
35        const viewWidth = window.innerWidth || document.documentElement.clientWidth;
36
37        return (
38          rect.bottom > 0 &&
39          rect.right > 0 &&
40          rect.top < viewHeight &&
41          rect.left < viewWidth
42        );
43      }
44
45      const target = document.getElementById("target");
46
47      window.addEventListener("scroll", () => {
48        console.log("partially visible:", isPartiallyVisible(target));
49      });
50    </script>
51  </body>
52</html>

This works well for one-off checks and simple pages. It is also easy to adapt for full visibility by requiring rect.top >= 0 and rect.bottom <= viewHeight, plus the equivalent horizontal checks.

Prefer IntersectionObserver for Ongoing Monitoring

If you need to react repeatedly as the user scrolls, IntersectionObserver is usually the better tool. The browser handles the observation efficiently and notifies your code only when the intersection state changes.

html
1<!doctype html>
2<html lang="en">
3  <body>
4    <div style="height: 1200px;"></div>
5    <section id="promo" style="height: 150px; background: lightgreen;">
6      Promotion block
7    </section>
8
9    <script>
10      const promo = document.getElementById("promo");
11
12      const observer = new IntersectionObserver(
13        (entries) => {
14          for (const entry of entries) {
15            if (entry.isIntersecting) {
16              console.log("Promo entered the viewport");
17            } else {
18              console.log("Promo left the viewport");
19            }
20          }
21        },
22        {
23          threshold: 0.25
24        }
25      );
26
27      observer.observe(promo);
28    </script>
29  </body>
30</html>

The threshold value controls how much of the element must be visible before the observer fires. A threshold of 0.25 means roughly one quarter of the element should overlap before the callback treats it as intersecting.

Scroll Containers Change the Rules

Many bugs happen because the page is not the thing that scrolls. A modal, side panel, or table container can have its own scrolling context. In that case, checking against the window viewport is the wrong coordinate system.

With IntersectionObserver, pass the scrolling container as root. With getBoundingClientRect, compare the target rectangle against the container rectangle instead of window.innerHeight.

That is the difference between code that works on a simple page and code that survives a real application layout.

Common Pitfalls

The first pitfall is doing expensive work on every scroll event. Scroll events fire frequently, and repeated layout reads can make a page feel sluggish. If you use direct checks, keep the handler small and throttle it when necessary.

Another pitfall is assuming visibility means the user can truly see the content. An element can intersect the viewport and still be covered by a fixed header, hidden by opacity: 0, or clipped by an ancestor with overflow: hidden. Geometric visibility is not always visual visibility.

Developers also often forget about horizontal visibility. On responsive pages, an element can be vertically present but pushed outside the horizontal viewport. If your UI matters on small screens, check both axes.

Finally, be careful with detached or null elements. If querySelector returns null, calling getBoundingClientRect will throw immediately. Validate the element before observing or measuring it.

Summary

  • Decide whether you need partial visibility or full visibility before writing the check.
  • Use getBoundingClientRect() for direct, simple visibility tests.
  • Use IntersectionObserver for efficient ongoing scroll-based observation.
  • Account for custom scroll containers, not just the browser window.
  • Visibility math is only part of the story; overlays and CSS clipping can still hide content.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.