Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I tell if a DOM element is visible in the current viewport?

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.)

like image 622
benzaita Avatar asked Sep 23 '08 21:09

benzaita


People also ask

How do you tell if an element is in the viewport?

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.

How do you know if an element is visible in the screen during scrolling?

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.

How much of an element is visible in viewport?

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.

How do you check if element is in viewport react?

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.


1 Answers

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() */     ); } 

How to use:

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:

  • Overlapping using z-index.
  • Using overflow-scroll in element's container.
  • Try something new - The Intersection Observer API explained.
like image 109
31 revs, 11 users 78% Avatar answered Sep 28 '22 03:09

31 revs, 11 users 78%