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));
};
Related protips:
Written by Steven Wade
Related protips
6 Responses
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!
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()
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());
});
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
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));
};
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)