Is there an efficient way to tell if a DOM element (in an HTML document) is currently visible (appears in the viewport)?
(The question refers to Firefox.)
If an element is in the viewport, it's position from the top and left will always be greater than or equal to 0 . It's distance from the right will be less than or equal to the total width of the viewport, and it's distance from the bottom will be less than or equal to the height of the viewport.
To know whether the element is fully visible in viewport, you will need to check whether top >= 0, and bottom is less than the screen height. In a similar way you can also check for partial visibility, top is less than screen height and bottom >= 0. The Javascript code could be written as : window.
So even if it's a part of a element but it covers the full height of the screen, it should be 100% in viewport.
To check if an element is in the viewport in React. js: Set the ref prop on the element. Use the IntersectionObserver API to track if the element is intersecting.
Now most browsers support getBoundingClientRect method, which has become the best practice. Using an old answer is very slow, not accurate and has several bugs.
The solution selected as correct is almost never precise.
This solution was tested on Internet Explorer 7 (and later), iOS 5 (and later) Safari, Android 2.0 (Eclair) and later, BlackBerry, Opera Mobile, and Internet Explorer Mobile 9.
function isElementInViewport (el) { // Special bonus for those using jQuery if (typeof jQuery === "function" && el instanceof jQuery) { el = el[0]; } var rect = el.getBoundingClientRect(); return ( rect.top >= 0 && rect.left >= 0 && rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /* or $(window).height() */ rect.right <= (window.innerWidth || document.documentElement.clientWidth) /* or $(window).width() */ ); }
You can be sure that the function given above returns correct answer at the moment of time when it is called, but what about tracking element's visibility as an event?
Place the following code at the bottom of your <body>
tag:
function onVisibilityChange(el, callback) { var old_visible; return function () { var visible = isElementInViewport(el); if (visible != old_visible) { old_visible = visible; if (typeof callback == 'function') { callback(); } } } } var handler = onVisibilityChange(el, function() { /* Your code go here */ }); // jQuery $(window).on('DOMContentLoaded load resize scroll', handler); /* // Non-jQuery if (window.addEventListener) { addEventListener('DOMContentLoaded', handler, false); addEventListener('load', handler, false); addEventListener('scroll', handler, false); addEventListener('resize', handler, false); } else if (window.attachEvent) { attachEvent('onDOMContentLoaded', handler); // Internet Explorer 9+ :( attachEvent('onload', handler); attachEvent('onscroll', handler); attachEvent('onresize', handler); } */
If you do any DOM modifications, they can change your element's visibility of course.
Guidelines and common pitfalls:
Maybe you need to track page zoom / mobile device pinch? jQuery should handle zoom/pinch cross browser, otherwise first or second link should help you.
If you modify DOM, it can affect the element's visibility. You should take control over that and call handler()
manually. Unfortunately, we don't have any cross browser onrepaint
event. On the other hand that allows us to make optimizations and perform re-check only on DOM modifications that can change an element's visibility.
Never Ever use it inside jQuery $(document).ready() only, because there is no warranty CSS has been applied in this moment. Your code can work locally with your CSS on a hard drive, but once put on a remote server it will fail.
After DOMContentLoaded
is fired, styles are applied, but the images are not loaded yet. So, we should add window.onload
event listener.
We can't catch zoom/pinch event yet.
The last resort could be the following code:
/* TODO: this looks like a very bad code */ setInterval(handler, 600);
You can use the awesome feature pageVisibiliy of the HTML5 API if you care if the tab with your web page is active and visible.
TODO: this method does not handle two situations:
z-index
.overflow-scroll
in element's container.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With