Checking if a div is visible within viewport using jquery

Viewed 21845

I am trying to use jquery to check if Div RED is within the viewport, and if not, then check if Div ORANGE is in the viewport. The function I am using works great if there is only one IF statement, but when I add another IF ELSE statement, it wont work.

here is the function:

$.fn.isOnScreen = function(){

    var win = $(window);

    var viewport = {
        top : win.scrollTop(),
        left : win.scrollLeft()
    };
    viewport.right = viewport.left + win.width();
    viewport.bottom = viewport.top + win.height();

    var bounds = this.offset();
    bounds.right = bounds.left + this.outerWidth();
    bounds.bottom = bounds.top + this.outerHeight();

    return (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));

};

here is the code I added to check and see if div red or div orange is within the viewport

$(window).scroll(function() {
    if ($('.red').isOnScreen() === true) { 
       $('.red').remove();
    } else if ($('.orange').isOnScreen() === true) {
       $('.orange').remove();   

    }
});

here is a jfiddle http://jsfiddle.net/wN7ah/453/

3 Answers

We can do it with pure javascript function like below

function elementInViewport2(el) {
  var top = el.offsetTop;
  var left = el.offsetLeft;
  var width = el.offsetWidth;
  var height = el.offsetHeight;

  while(el.offsetParent) {
    el = el.offsetParent;
    top += el.offsetTop;
    left += el.offsetLeft;
  }

  return (
    top < (window.pageYOffset + window.innerHeight) &&
    left < (window.pageXOffset + window.innerWidth) &&
    (top + height) > window.pageYOffset &&
    (left + width) > window.pageXOffset
  );
}
ele = document.getElementById('visb_true');
console.log("visible: ", elementInViewport2(ele))
ele = document.getElementById('visb_false');
console.log("visible: ", elementInViewport2(ele))
#visb_true{
    color: green;
    font-weight: 800;
}

#visb_false{
    color: red;
    font-weight: 800;
}
<html>
<body>
<p> hello </p>
<p> hello </p>
<p id="visb_true"> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p>
<p> hello </p><p> hello </p>
<p id="visb_false"> hello </p>
<p> hello </p>
</body>
</html>

The modern way to do this is by using the Intersection Observer API. This is an excellent documentation, the following are basically just excerpts from it. It works with all modern browsers.

First, create an Intersection Observer:

let options = {
    root: document.querySelector('#scrollArea'), // null for entire viewport 
    rootMargin: '0px',
    threshold: 1.0
}
let observer = new IntersectionObserver(callback, options);

Then target an element (or multiple elements) to watch:

let target = document.querySelector('#watchItem');
observer.observe(target);

Lastly, the callback. It receives a list of all watched items entries. Check the value of the isIntersecting property to see if the entry represents an element that currently intersects with the root.

let callback = (entries, observer) => {
    entries.forEach(entry => {
        if(entry.isIntersecting) {
            // Do your thing
        }
    });
};
Related