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.
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.
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.
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
IntersectionObserverfor 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
- How to check if object is an array of a certain type?
- How to check if object property exists with a variable holding the property name?
- How to check internet connection in React Native application for both iOS and Android?
- How to check the existence of Kafka topic in Nodejs
- How to check whether an object is a date?
- How to clear react-native cache?
- How to combine a pagination with Observables and the AsyncPipe in Angular 9?
- How to compare arrays in JavaScript?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack 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.