1392

I'm loading elements via AJAX. Some of them are only visible if you scroll down the page. Is there any way I can know if an element is now in the visible part of the page?

Kerem
11.6k5 gold badges61 silver badges58 bronze badges
asked Jan 28, 2009 at 10:00
11
  • 61
    he means that he wants a method to know if a given element is displayed in the browser window, or if the user needs to scroll to see it. Commented Jan 28, 2009 at 10:14
  • 1
    To check if an element is fully visible in a container, just add an extra selector param and re-use the elem code for it. Library.IsElementVisibleInContainer = function (elementSelector, containerSelector) { var containerViewTop = $(containerSelector).offset().top; var containerViewBottom = containerViewTop + $(containerSelector).height(); Commented Oct 30, 2012 at 11:25
  • 4
    possible duplicate of How to tell if a DOM element is visible in the current viewport? Commented Feb 20, 2013 at 20:27
  • 1
    Possible duplicate of How to tell if a DOM element is visible in the current viewport? Commented Jul 19, 2018 at 6:28
  • 4
    All answers will trigger reflow so it could be bottle neck, you shout use IntersectionObserver if supported. It will have better performance on modern browsers, Commented Apr 6, 2019 at 19:51

47 Answers 47

1
2
1348

This should do the trick:

function isScrolledIntoView(elem)
{
 var docViewTop = $(window).scrollTop();
 var docViewBottom = docViewTop + $(window).height();
 var elemTop = $(elem).offset().top;
 var elemBottom = elemTop + $(elem).height();
 return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}

Simple Utility Function This will allow you to call a utility function that accepts the element you're looking for and if you want the element to be fully in view or partially.

function Utils() {
}
Utils.prototype = {
 constructor: Utils,
 isElementInView: function (element, fullyInView) {
 var pageTop = $(window).scrollTop();
 var pageBottom = pageTop + $(window).height();
 var elementTop = $(element).offset().top;
 var elementBottom = elementTop + $(element).height();
 if (fullyInView === true) {
 return ((pageTop < elementTop) && (pageBottom > elementBottom));
 } else {
 return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
 }
 }
};
var Utils = new Utils();

Usage

var isElementInView = Utils.isElementInView($('#flyout-left-container'), false);
if (isElementInView) {
 console.log('in view');
} else {
 console.log('out of view');
}
Andrea Casaccia
5,0014 gold badges33 silver badges55 bronze badges
answered Jan 28, 2009 at 15:36
Sign up to request clarification or add additional context in comments.

5 Comments

Note that this only works if the document is the element being scrolled, i.e. you aren't checking visibility of some element inside a scrolling inner pane.
For: "Any part of the element in view", I used: ((( elemTop >= docViewTop) && (elemTop <= docViewBottom)) || ((elemBottom >= docViewTop) && (elemBottom <= docViewBottom)))
This works fine when the element is in open document, this gives inappropriate result when use for element inside some scrollable division, I tried replacing $(window) with $("somediv") still no accurate result, how can I get accurate result on this?.
You might also want to check out this method, which is not (yet) standard, but hopefully becomes standard in the future. It makes these calculations uneccessary in cases where you just want to scroll an element into view: developer.mozilla.org/en-US/docs/Web/API/Element/…
This solution works only with jQuery.
560

This answer in Vanilla:

function isScrolledIntoView(el) {
 var rect = el.getBoundingClientRect();
 var elemTop = rect.top;
 var elemBottom = rect.bottom;
 // Only completely visible elements return true:
 var isVisible = (elemTop >= 0) && (elemBottom <= window.innerHeight);
 // Partially visible elements return true:
 //isVisible = elemTop < window.innerHeight && elemBottom >= 0;
 return isVisible;
}
jcubic
67k58 gold badges252 silver badges466 bronze badges
answered Mar 18, 2014 at 13:31

6 Comments

shouldn't this be isVisible = elementTop < window.innerHeight && elementBottom >= 0? Otherwise an element half on the screen returns false.
no. i check if some element is fully visible on the page. if you want to check visibility of some part - you can customise this snippet.
I find this answer to perform better than the chosen answer. Simpler too.
In comparison to the approved answer, this performs waaaay much better with hundreds of elements.
No, it does not work for the purpose. Let's say, el is in the scrolled container, and below this container, there is something else, say, a status bar. If the scrolling is positioned so the el is under this status bar, isScrolledIntoView(el) will return true if the status bar covers the part of el. The correct solution would be using getBoundingClientRect() of the element that can be scrolled to bring el into view. Unfortunately, scrollIntoView performs redundant scrolling in some cases, so correct isScrolledIntoView...
|
188

Using IntersectionObserver API

(native in modern browsers)


It's easy & efficient to determine if an element is visible in the viewport, or in any scrollable container, by using an observer.

The need to attach a scroll event and manually checking on the event callback is eliminated, which is more efficient:

// define an observer instance
var observer = new IntersectionObserver(onIntersection, {
 root: null, // default is the viewport
 threshold: .5 // percentage of target's visible area. Triggers "onIntersection"
})
// callback is called on intersection change
function onIntersection(entries, opts){
 entries.forEach(entry => 
 entry.target.classList.toggle('visible', entry.isIntersecting)
 )
}
// Use the observer to observe an element
observer.observe( document.querySelector('.box') )
// To stop observing:
// observer.unobserve(entry.target)
span{ position:fixed; top:0; left:0; }
.box{ width:100px; height:100px; background:red; margin:1000px; transition:.75s; }
.box.visible{ background:green; border-radius:50%; }
<span>Scroll both Vertically &amp; Horizontally...</span>
<div class='box'></div>


Supported by modern browsers, including mobile browsers. Not supported in IE - View browsers support table

Vikrant Bhat
2,6384 gold badges19 silver badges33 bronze badges
answered Aug 10, 2017 at 15:44

2 Comments

Safari is the new IE, everything I would like to implement these days is supported by all evergreen browsers... except safari
Safari has supported IntersectionObserver since 2019
133

Update: use IntersectionObserver


The best method I have found so far is the jQuery appear plugin. Works like a charm.

Mimics a custom "appear" event, which fires when an element scrolls into view or otherwise becomes visible to the user.

$('#foo').appear(function() {
 $(this).text('Hello world');
});

This plugin can be used to prevent unnecessary requests for content that's hidden or outside the viewable area.

answered Aug 20, 2010 at 21:31

3 Comments

This is a cool plugin, no doubt, but doesn't answer the question.
Is there a disappear plugin?
$('#disappear-plugin')
104

Here's my pure JavaScript solution that works if it's hidden inside a scrollable container too.

Demo here (try resizing the window too)

var visibleY = function(el){
 var rect = el.getBoundingClientRect(), top = rect.top, height = rect.height, 
 el = el.parentNode
 // Check if bottom of the element is off the page
 if (rect.bottom < 0) return false
 // Check its within the document viewport
 if (top > document.documentElement.clientHeight) return false
 do {
 rect = el.getBoundingClientRect()
 if (top <= rect.bottom === false) return false
 // Check if the element is out of view due to a container scrolling
 if ((top + height) <= rect.top) return false
 el = el.parentNode
 } while (el != document.body)
 return true
};

EDIT 2016年03月26日: I've updated the solution to account for scrolling past the element so it's hidden above the top of the scroll-able container. EDIT 2018年10月08日: Updated to handle when scrolled out of view above the screen.

answered Feb 7, 2014 at 12:02

3 Comments

+1 This was the only coded (i.e. not third party) answer that takes into account the recursive nature of elements. I've expanded to handle horizontal, vertical and page scroll: jsfiddle.net/9nuqpgqa
Angular version here: stackblitz.com/edit/angular-ivy-hsnnia - includes identifying which rows of a table are visible.
The solution from @Pebbl is very useful, but doesn't account for elements with overflow: auto
65

Plain vanilla to check if element (el) is visible in scrollable div (holder)

function isElementVisible (el, holder) {
 holder = holder || document.body
 const { top, bottom, height } = el.getBoundingClientRect()
 const holderRect = holder.getBoundingClientRect()
 return top <= holderRect.top
 ? holderRect.top - top <= height
 : bottom - holderRect.bottom <= height
}

Usage with jQuery:

var el = $('tr:last').get(0);
var holder = $('table').get(0);
var isVisible = isElementVisible(el, holder);
Abijeet Patro
2,8844 gold badges39 silver badges65 bronze badges
answered Jan 20, 2017 at 1:37

3 Comments

In this era of Single Page Applications it has become more common to check if an element is visible within some other element besides window. That's why this one gets my upvote.
NOTE: If you want to have this return based on any part of the element not being visible (as was in my case), remove the height variable from the function and change the places it's used to just 0 (zero). Then if you have only "part" of the element hidden, it will return false.
Why your function name in the jQuery usage is different?
40

jQuery Waypoints plugin goes very nice here.

$('.entry').waypoint(function() {
 alert('You have scrolled to an entry.');
});

There are some examples on the site of the plugin.

answered Dec 4, 2011 at 12:08

1 Comment

For me it only worked with an offset $('#my-div').waypoint(function() { console.log('Hello there!'); }, { offset: '100%' });
27

How about

function isInView(elem){
 return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;
}

After that you can trigger whatever you want once the element is in view like this

$(window).scroll(function(){
 if (isInView($('.classOfDivToCheck')))
 //fire whatever you what 
 dothis();
})

That works for me just fine

sectus
15.7k5 gold badges59 silver badges97 bronze badges
answered Apr 29, 2014 at 10:24

Comments

16

Tweeked Scott Dowding's cool function for my requirement- this is used for finding if the element has just scrolled into the screen i.e it's top edge .

function isScrolledIntoView(elem)
{
 var docViewTop = $(window).scrollTop();
 var docViewBottom = docViewTop + $(window).height();
 var elemTop = $(elem).offset().top;
 return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}
answered Apr 30, 2013 at 16:08

Comments

15

WebResourcesDepot wrote a script to load while scrolling that uses jQuery some time ago. You can view their Live Demo Here. The beef of their functionality was this:

$(window).scroll(function(){
 if ($(window).scrollTop() == $(document).height() - $(window).height()){
 lastAddedLiveFunc();
 }
});
function lastAddedLiveFunc() { 
 $('div#lastPostsLoader').html('<img src="images/bigLoader.gif">');
 $.post("default.asp?action=getLastPosts&lastPostID="+$(".wrdLatest:last").attr("id"),
 function(data){
 if (data != "") {
 $(".wrdLatest:last").after(data); 
 }
 $('div#lastPostsLoader').empty();
 });
};
answered Jan 28, 2009 at 14:14

Comments

15

Most answers here don't take into account that an element can also be hidden because it is scrolled out of view of a div, not only of the whole page.

To cover that possibility, you basically have to check if the element is positioned inside the bounds of each of its parents.

This solution does exactly that:

function(element, percentX, percentY){
 var tolerance = 0.01; //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimals
 if(percentX == null){
 percentX = 100;
 }
 if(percentY == null){
 percentY = 100;
 }
 var elementRect = element.getBoundingClientRect();
 var parentRects = [];
 while(element.parentElement != null){
 parentRects.push(element.parentElement.getBoundingClientRect());
 element = element.parentElement;
 }
 var visibleInAllParents = parentRects.every(function(parentRect){
 var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
 var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
 var visiblePercentageX = visiblePixelX / elementRect.width * 100;
 var visiblePercentageY = visiblePixelY / elementRect.height * 100;
 return visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY;
 });
 return visibleInAllParents;
};

It also lets you specify to what percentage it has to be visible in each direction.
It doesn't cover the possibility that it may be hidden due to other factors, like display: hidden.

This should work in all major browsers, since it only uses getBoundingClientRect. I personally tested it in Chrome and Internet Explorer 11.

answered Jun 26, 2016 at 13:35

4 Comments

Thank you for this code. I wonder how you would add the event listener on scroll in this case that you have multiple nested scrollable elements? It seems like adding the listener to window alone is not enough, do we have to traverse back to the top parent to add the listener to each scrollable container?
@mr1031011 It should be possible to add the handler to window and then check for the target to identify the container that was scrolled.
right, it doesn't work with the example given by @vanowm,
This fails the simplest test with a button below the viewport, misreports the button as visible: jsfiddle - see the fiddle's Console. Or is this some kind of jsfiddle iframe limitation that wouldn't happen in reality? It also doesn't handle <html style="overflow: hidden auto; height: 100%; properly, which is what jQuery UI Layout plugin does.
11

The easiest solution I found for this is Intersection Observer API:

var observer = new IntersectionObserver(function(entries) {
 if(entries[0].isIntersecting === true)
 console.log('Element has just become visible in screen');
}, { threshold: [0] });
observer.observe(document.querySelector("#main-container"));
answered Jan 2, 2020 at 10:52

Comments

9

isScrolledIntoView is a very needful function, so I tried it, it works for elements not heigher than the viewport, but if the element is bigger as the viewport it does not work. To fix this easily change the condition:

return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));

to this:

return (docViewBottom >= elemTop && docViewTop <= elemBottom);

See a demo jsfiddle here.

answered Oct 23, 2013 at 17:30

Comments

8

I needed to check visibility in elements inside scrollable DIV container

 //p = DIV container scrollable
 //e = element
 function visible_in_container(p, e) {
 var z = p.getBoundingClientRect();
 var r = e.getBoundingClientRect();
 // Check style visiblilty and off-limits
 return e.style.opacity > 0 && e.style.display !== 'none' &&
 e.style.visibility !== 'hidden' &&
 !(r.top > z.bottom || r.bottom < z.top ||
 r.left > z.right || r.right < z.left);
 }
Brett Zamir
14.4k7 gold badges57 silver badges85 bronze badges
answered Apr 25, 2013 at 9:33

Comments

8

This considers any padding, border or margin the element has as well as elements larger than the viewport itself.

function inViewport($ele) {
 var lBound = $(window).scrollTop(),
 uBound = lBound + $(window).height(),
 top = $ele.offset().top,
 bottom = top + $ele.outerHeight(true);
 return (top > lBound && top < uBound)
 || (bottom > lBound && bottom < uBound)
 || (lBound >= top && lBound <= bottom)
 || (uBound >= top && uBound <= bottom);
}

To call it use something like this:

var $myElement = $('#my-element'),
 canUserSeeIt = inViewport($myElement);
console.log(canUserSeeIt); // true, if element is visible; false otherwise
answered Dec 30, 2014 at 1:54

Comments

8

Here is another solution:

<script type="text/javascript">
$.fn.is_on_screen = 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));
 };
if( $('.target').length > 0 ) { // if target element exists in DOM
 if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
 $('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info 
 } else {
 $('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
 }
}
$(window).on('scroll', function(){ // bind window scroll event
if( $('.target').length > 0 ) { // if target element exists in DOM
 if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
 $('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info
 } else {
 $('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
 }
}
});
</script>

See it in JSFiddle

answered Feb 15, 2014 at 18:51

Comments

7
function isScrolledIntoView(elem) {
 var docViewTop = $(window).scrollTop(),
 docViewBottom = docViewTop + $(window).height(),
 elemTop = $(elem).offset().top,
 elemBottom = elemTop + $(elem).height();
 //Is more than half of the element visible
 return ((elemTop + ((elemBottom - elemTop)/2)) >= docViewTop && ((elemTop + ((elemBottom - elemTop)/2)) <= docViewBottom));
}
answered Oct 9, 2009 at 9:49

Comments

7

Building off of this great answer, you can simplify it a little further using ES2015+:

function isScrolledIntoView(el) {
 const { top, bottom } = el.getBoundingClientRect()
 return top >= 0 && bottom <= window.innerHeight
}

If you don't care about the top going out of the window and just care that the bottom has been viewed, this can be simplified to

function isSeen(el) {
 return el.getBoundingClientRect().bottom <= window.innerHeight
}

or even the one-liner

const isSeen = el => el.getBoundingClientRect().bottom <= window.innerHeight
answered Mar 14, 2017 at 3:20

Comments

7

There is a plugin for jQuery called inview which adds a new "inview" event.


Here is some code for a jQuery plugin that doesn't use events:

$.extend($.expr[':'],{
 inView: function(a) {
 var st = (document.documentElement.scrollTop || document.body.scrollTop),
 ot = $(a).offset().top,
 wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
 return ot > st && ($(a).height() + ot) < (st + wh);
 }
});
(function( $ ) {
 $.fn.inView = function() {
 var st = (document.documentElement.scrollTop || document.body.scrollTop),
 ot = $(this).offset().top,
 wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
 return ot > st && ($(this).height() + ot) < (st + wh);
 };
})( jQuery );

I found this in a comment here ( http://remysharp.com/2009/01/26/element-in-view-event-plugin/ ) by a bloke called James

answered Sep 26, 2012 at 16:05

Comments

6

The Javascript code could be written as :

window.addEventListener('scroll', function() {
 var element = document.querySelector('#main-container');
 var position = element.getBoundingClientRect();
 // checking whether fully visible
 if(position.top >= 0 && position.bottom <= window.innerHeight) {
 console.log('Element is fully visible in screen');
 }
 // checking for partial visibility
 if(position.top < window.innerHeight && position.bottom >= 0) {
 console.log('Element is partially visible in screen');
 }
});

and in react js written as:

 componentDidMount() {
 window.addEventListener('scroll', this.isScrolledIntoView);
 }
 componentWillUnmount() {
 window.removeEventListener('scroll', this.isScrolledIntoView);
 }
 
 isScrolledIntoView() {
 var element = document.querySelector('.element');
 var position = element.getBoundingClientRect();
 // checking whether fully visible
 if (position.top >= 0 && position.bottom <= window.innerHeight) {
 console.log('Element is fully visible in screen');
 }
 // checking for partial visibility
 if (position.top < window.innerHeight && position.bottom >= 0) {
 console.log('Element is partially visible in screen');
 }
 }

answered Oct 20, 2021 at 7:55

Comments

5

I have such a method in my application, but it does not use jQuery:

/* Get the TOP position of a given element. */
function getPositionTop(element){
 var offset = 0;
 while(element) {
 offset += element["offsetTop"];
 element = element.offsetParent;
 }
 return offset;
}
/* Is a given element is visible or not? */
function isElementVisible(eltId) {
 var elt = document.getElementById(eltId);
 if (!elt) {
 // Element not found.
 return false;
 }
 // Get the top and bottom position of the given element.
 var posTop = getPositionTop(elt);
 var posBottom = posTop + elt.offsetHeight;
 // Get the top and bottom position of the *visible* part of the window.
 var visibleTop = document.body.scrollTop;
 var visibleBottom = visibleTop + document.documentElement.offsetHeight;
 return ((posBottom >= visibleTop) && (posTop <= visibleBottom));
}

Edit : This method works well for I.E. (at least version 6). Read the comments for compatibility with FF.

answered Jan 28, 2009 at 10:17

Comments

5

I prefer using jQuery expr

jQuery.extend(jQuery.expr[':'], { 
 inview: function (elem) {
 var t = $(elem);
 var offset = t.offset();
 var win = $(window); 
 var winST = win.scrollTop();
 var elHeight = t.outerHeight(true);
 if ( offset.top > winST - elHeight && offset.top < winST + elHeight + win.height()) {
 return true; 
 } 
 return false; 
 }
});

so you can use it this way

$(".my-elem:inview"); //returns only element that is in view
$(".my-elem").is(":inview"); //check if element is in view
$(".my-elem:inview").length; //check how many elements are in view

You can easly add such code inside scroll event function etc. to check it everytime user will scroll the view.

answered Feb 22, 2015 at 23:33

Comments

4

If you want to tweak this for scrolling item within another div,

function isScrolledIntoView (elem, divID) 
{
 var docViewTop = $('#' + divID).scrollTop();
 var docViewBottom = docViewTop + $('#' + divID).height();
 var elemTop = $(elem).offset().top;
 var elemBottom = elemTop + $(elem).height();
 return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); 
}
answered Feb 14, 2013 at 18:49

Comments

4

You can make use of jquery plugin "onScreen" to check if the element is in the current viewport when you scroll. The plugin sets the ":onScreen" of the selector to true when the selector appears on the screen. This is the link for the plugin which you can include in your project. "http://benpickles.github.io/onScreen/jquery.onscreen.min.js"

You can try the below example which works for me.

$(document).scroll(function() {
 if($("#div2").is(':onScreen')) {
 console.log("Element appeared on Screen");
 //do all your stuffs here when element is visible.
 }
 else {
 console.log("Element not on Screen");
 //do all your stuffs here when element is not visible.
 }
});

HTML Code:

<div id="div1" style="width: 400px; height: 1000px; padding-top: 20px; position: relative; top: 45px"></div> <br>
<hr /> <br>
<div id="div2" style="width: 400px; height: 200px"></div>

CSS:

#div1 {
 background-color: red;
}
#div2 {
 background-color: green;
}
answered Mar 4, 2015 at 11:34

Comments

4

An example based off of this answer to check if an element is 75% visible (i.e. less than 25% of it is off of the screen).

function isScrolledIntoView(el) {
 // check for 75% visible
 var percentVisible = 0.75;
 var elemTop = el.getBoundingClientRect().top;
 var elemBottom = el.getBoundingClientRect().bottom;
 var elemHeight = el.getBoundingClientRect().height;
 var overhang = elemHeight * (1 - percentVisible);
 var isVisible = (elemTop >= -overhang) && (elemBottom <= window.innerHeight + overhang);
 return isVisible;
}
answered Apr 17, 2015 at 23:22

Comments

3

Modified the accepted answer so that the element has to have it's display property set to something other than "none" to quality as visible.

function isScrolledIntoView(elem) {
 var docViewTop = $(window).scrollTop();
 var docViewBottom = docViewTop + $(window).height();
 var elemTop = $(elem).offset().top;
 var elemBottom = elemTop + $(elem).height();
 var elemDisplayNotNone = $(elem).css("display") !== "none";
 return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop) && elemDisplayNotNone);
}
answered Sep 16, 2013 at 20:02

Comments

3

Here is a way to achieve the same thing using Mootools, in horizontal, vertical or both.

Element.implement({
inVerticalView: function (full) {
 if (typeOf(full) === "null") {
 full = true;
 }
 if (this.getStyle('display') === 'none') {
 return false;
 }
 // Window Size and Scroll
 var windowScroll = window.getScroll();
 var windowSize = window.getSize();
 // Element Size and Scroll
 var elementPosition = this.getPosition();
 var elementSize = this.getSize();
 // Calculation Variables
 var docViewTop = windowScroll.y;
 var docViewBottom = docViewTop + windowSize.y;
 var elemTop = elementPosition.y;
 var elemBottom = elemTop + elementSize.y;
 if (full) {
 return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
 && (elemBottom <= docViewBottom) && (elemTop >= docViewTop) );
 } else {
 return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
 }
},
inHorizontalView: function(full) {
 if (typeOf(full) === "null") {
 full = true;
 }
 if (this.getStyle('display') === 'none') {
 return false;
 }
 // Window Size and Scroll
 var windowScroll = window.getScroll();
 var windowSize = window.getSize();
 // Element Size and Scroll
 var elementPosition = this.getPosition();
 var elementSize = this.getSize();
 // Calculation Variables
 var docViewLeft = windowScroll.x;
 var docViewRight = docViewLeft + windowSize.x;
 var elemLeft = elementPosition.x;
 var elemRight = elemLeft + elementSize.x;
 if (full) {
 return ((elemRight >= docViewLeft) && (elemLeft <= docViewRight)
 && (elemRight <= docViewRight) && (elemLeft >= docViewLeft) );
 } else {
 return ((elemRight <= docViewRight) && (elemLeft >= docViewLeft));
 }
},
inView: function(full) {
 return this.inHorizontalView(full) && this.inVerticalView(full);
}});
answered Jun 14, 2014 at 20:59

Comments

3

This method will return true if any part of the element is visible on the page. It worked better in my case and may help someone else.

function isOnScreen(element) {
 var elementOffsetTop = element.offset().top;
 var elementHeight = element.height();
 var screenScrollTop = $(window).scrollTop();
 var screenHeight = $(window).height();
 var scrollIsAboveElement = elementOffsetTop + elementHeight - screenScrollTop >= 0;
 var elementIsVisibleOnScreen = screenScrollTop + screenHeight - elementOffsetTop >= 0;
 return scrollIsAboveElement && elementIsVisibleOnScreen;
}
answered Aug 15, 2014 at 14:23

Comments

3

I have written a component for the task, designed to handle large numbers of elements extremely fast (to the tune of <10ms for 1000 elements on a slow mobile).

It works with every type of scroll container you have access to – window, HTML elements, embedded iframe, spawned child window – and is very flexible in what it detects (full or partial visibility, border box or content box, custom tolerance zone, etc).

A huge, mostly auto-generated test suite ensures that it works as advertised, cross-browser.

Give it a shot if you like: jQuery.isInView. Otherwise, you might find inspiration in the source code, e.g. here.

answered Mar 5, 2015 at 17:02

Comments

3

There are over 30 answers to this question, and none of them use the amazingly simple, pure JS solution that I have been using. There is no need to load jQuery just to solve this, as many others are pushing.

In order to tell if the element is within the viewport, we must first determine the elements position within the body. We do not need to do this recursively as I once thought. Instead, we can use element.getBoundingClientRect().

pos = elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top;

This value is the Y difference between the top of the object and the top of the body.

We then must tell if the element is within view. Most implementations ask if the full element is within the viewport, so this is what we shall cover.

First of all, the top position of the window is: window.scrollY.

We can get the bottom position of the window by adding the window's height to its top position:

var window_bottom_position = window.scrollY + window.innerHeight;

Lets create a simple function for getting the element's top position:

function getElementWindowTop(elem){
 return elem && typeof elem.getBoundingClientRect === 'function' ? elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top : 0;
}

This function will return the element's top position within the window or it will return 0 if you pass it something other than an element with the .getBoundingClientRect() method. This method has been around for a long time, so you shouldn't have to worry about your browser not supporting it.

Now, our element's top position is:

var element_top_position = getElementWindowTop(element);

And or element's bottom position is:

var element_bottom_position = element_top_position + element.clientHeight;

Now we can determine if the element is within the viewport by checking if the element's bottom position is lower than the viewport's top position and by checking if the element's top position is higher than the viewport's bottom position:

if(element_bottom_position >= window.scrollY 
&& element_top_position <= window_bottom_position){
 //element is in view
else
 //element is not in view

From there, you can perform the logic to add or remove an in-view class on your element, which you can then handle later with transition effects in your CSS.

I am absolutely amazed that I did not find this solution anywhere else, but I do believe that this is the cleanest and most effective solution, and it doesn't require you to load jQuery!

answered Sep 26, 2016 at 17:35

Comments

1
2

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.