Last Updated: July 04, 2023
·
113.6K
· stevenwadejr

jQuery - Test if element is in viewport

Just came across this little beauty...

Test to determine if an element is visible within the viewport of the browser.

My thanks and compliments to the original author.

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

};

Original post

jsFiddle Example

Related protips:

fatal: refusing to merge unrelated histories

6 Responses
Add your response

This uses a callback (http://jsfiddle.net/LAJNz/1/):

$.fn.isOnScreen = function (cbTrue, cbFalse) {

    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();

    var isOnScreen = (!(viewport.right < bounds.left || viewport.left > bounds.right || viewport.bottom < bounds.top || viewport.top > bounds.bottom));

    return isOnScreen
      ? cbTrue && cbTrue(viewport, bounds)
      : cbFalse && cbFalse(viewport, bounds);
};

SECOND EDIT IS NOT REFLECTED IN JSFIDDLE!

over 1 year ago ·

This doesn't seem to determine if the object is in the viewport, it simply detects if the the element has been scrolled past.

i.e. it returns true even if the element is at the bottom of the page (out of the viewport), and your viewport is at the top, and only returns false once the element leaves the top of the viewport.

So it's more HasThisElementBeenScrolledPast()

over 1 year ago ·

i wrote this one

$.fn.inView = function(){
    //Window Object
    var win = $(window);
    //Object to Check
    obj = $(this);
    //the top Scroll Position in the page
    var scrollPosition = win.scrollTop();
    //the end of the visible area in the page, starting from the scroll position
    var visibleArea = win.scrollTop() + win.height();
    //the end of the object to check
    var objEndPos = (obj.offset().top + obj.outerHeight());
    return(visibleArea >= objEndPos && scrollPosition <= objEndPos ? true : false)
};


$(window).scroll(function(){
    alert($("#obj").inView());
});
over 1 year ago ·

var objEndPos = (obj.offset().top + win.height());

i my opinion this objEndPos , in this way will be more useful , beacause your approach will give false untill i have completely scroll down for obj section.

But this way , it will return true once obj div is covered on screen.
BTW Thank you

over 1 year ago ·

Great example but I had to customize it in order to scroll up/down if top/bottom portion of element was not in viewport. I also stripped out horizontal checks as I only need to scroll vertically to selected element.


$.fn.isOnScreen = function(el){
var win = $(window);
var bounds = el.offset();

var viewport = {
top : win.scrollTop()
};

viewport.bottom = viewport.top + win.height();
bounds.bottom = bounds.top + el.outerHeight();

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

over 1 year ago ·

Here is a version that only requires vanilla JS:

var isOnScreen = function (element) {
         var w = window,
               elBounds = element.getBoundingClientRect(),
               scrollTop = w.pageYOffset,
               elTop = elBounds.y + scrollTop;

         return (
            elTop < (w.innerHeight + scrollTop) &&
            elTop > (scrollTop - elBounds.height)
         );
       }

And here is the modern way to write it:

const isOnScreen = (element) => {
          const w = window,
                    elBounds = element.getBoundingClientRect(),
                    scrollTop = w.pageYOffset,
                    elTop = elBounds.y + scrollTop;

          return (
              elTop < (w.innerHeight + scrollTop) &&
              elTop > (scrollTop - elBounds.height)
          );
        }

with the element argument being any single node, like what is returned by getElementById (though this is not the only way to grab an element obviously)

over 1 year ago ·