By yoavf


2009-01-28 10:00:55 8 Comments

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?

30 comments

@vsync 2017-08-10 15:44:42

Using the ("new") IntersectionObserver API

it's very easy and efficient to determine if an element visible in the viewport. By using an observer, it eliminates the need to attach a scroll event and manually checking on the event callback.

// this is the target which is observed
var target = document.querySelector('div');

// configure the intersection observer instance
var intersectionObserverOptions = {
  root: null,
  rootMargin: '150px',
  threshold: 1.0
}
    
var observer = new IntersectionObserver(onIntersection, intersectionObserverOptions);

// provide the observer with a target
observer.observe(target);

function onIntersection(entries){
  entries.forEach(entry => {
    console.clear();
    console.log(entry.intersectionRatio)
    target.classList.toggle('visible', entry.intersectionRatio > 0);
    
    // Are we in viewport?
    if (entry.intersectionRatio > 0) {
      // Stop watching 
      // observer.unobserve(entry.target);
    }
  });
}
.box{ width:100px; height:100px; background:red; margin:1000px; }
.box.visible{ background:green; }
Scroll both Vertically & Horizontally...
<div class='box'></div>


View browsers support table (not supported in IE/Safari)

@Matt Wilson 2018-03-08 17:42:05

Thanks! This works for me and also got it working in IE11 with github.com/w3c/IntersectionObserver

@Fabian von Ellerts 2018-11-08 10:39:28

By far the best solution. Worked in IE11 without polyfill!

@Leland 2019-02-20 23:37:02

Note that this STILL isn't supported in iOS/macOS Safari, unfortunately. Make sure to check perf issues if you choose to polyfill, that's a large group of users

@vsync 2019-02-21 08:07:48

@Leland - it's project-dependent. for all my projects this is an absolute 0 users group. I don't build websites but web system ;)

@Zeni 2019-03-28 15:35:26

Best in class, wish its compatibility could be higher.

@Alireza 2019-01-31 04:32:38

We can do something like this in modern browsers using ES6:

const isFullySeen = el => el &&
  typeof el.getBoundingClientRect === 'function' &&
  el.getBoundingClientRect()['bottom'] + window.scrollY <= 
    window.innerHeight + window.scrollY && 
  el.getBoundingClientRect()['top'] + window.scrollY <= 
    window.innerHeight + window.scrollY;

@Denis Matafonov 2017-01-20 01:37:52

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);
isVisible =  isScrolledIntoView(el, holder);

@Ally 2014-02-07 12:02:25

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.

@Yousef Salimpour 2014-06-15 08:53:08

thanks, maybe better be return top <= document.documentElement.clientHeight && top >= 0;

@Pebbl 2014-10-03 12:24:19

+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

@Wojciech Jakubas 2016-02-07 10:36:27

This solution only checks top of the element. If first top pixel is visible, it will return true even if the rest of the item is not visible. To check if entire element is visible, you need to check bottom property too.

@Roamer-1888 2017-02-15 12:06:50

Aye, neat! Used to help write this answer (with credit as js comment).

@Mikhail Ramendik 2017-10-19 00:07:03

Missing ; after the second "return false" in the loop

@vanowm 2018-02-18 16:14:37

Unfortunately doesn't work: jsfiddle.net/vanowm/hmmv4gLr/24

@KSPR 2018-09-06 12:51:58

Where in that code do I have to place my function whcih I want to call when the element is visible?

@mr1031011 2018-10-26 17:10:12

There are edge cases that this solution just do not work.

@ness-EE 2012-09-26 16:05:32

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

@mikemaccana 2014-12-15 17:49:39

Alas, jQuery inview is no longer maintained and does not work with current versions of jQuery.

@ness-EE 2014-12-17 10:46:14

um... it works for me on 1.11.1 which is a current version

@mikemaccana 2014-12-17 11:18:13

JQuery 1 is for legacy browser support, new features are in jQuery 2.

@Matthew Bonner 2016-11-18 14:36:33

Link does not show the example as the page has been updated.

@bravedick 2014-03-18 13:31:11

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;
}

@gman 2015-02-23 21:08:23

shouldn't this be isVisible = elementTop < window.innerHeight && elementBottom >= 0? Otherwise an element half on the screen returns false.

@bravedick 2015-02-24 08:45:25

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.

@Adam Venezia 2015-07-15 16:54:29

I find this answer to perform better than the chosen answer. Simpler too.

@Jony-Y 2016-01-01 11:51:53

the element.getBoundingClientRect bottom and top gave me the right idea. +1

@ncla 2016-02-15 00:05:54

In comparison to the approved answer, this performs waaaay much better with hundreds of elements.

@gcampbell 2016-06-06 19:40:17

Is there any particular reason jQuery is favoured over vanilla on SO?

@Marc Diethelm 2016-06-30 16:26:28

@gcampbell Yes, people are afraid of using the DOM or don't know the API or just plain forget it exists. Even though in many cases jQuery is not needed anymore it has unfortunately become a de facto standard. In all fairness, the DOM like most web technologies is not fun to use, at all.

@gcampbell 2016-06-30 20:28:15

@MarcDiethelm Especially with namespaces e.g. SVG.

@guari 2016-07-22 12:19:20

the function will return always false if the element is visible but it's wider than the scroll area

@bravedick 2016-07-25 19:57:17

@guari sure, cause visible here means visible, and not partially visible ;)

@SkyWriter 2017-02-16 05:57:29

I'd cache the result of el.getBoundingClientRect() in a variable instead of calling it twice to squeeze out some free performance boost.

@upInCloud 2017-04-03 10:25:00

see a small fiddle demonstrating here - jsfiddle.net/shaaraddalvi/4rp09jL0

@kyw 2018-07-27 10:10:48

getBoundingClientRect() causes "layout thrashing". Any suggestion how to make scrolling in this respect performant?

@mondi 2019-05-23 15:07:05

Does this work on iphones and so..?

@Damilola Boiyelove 2017-08-21 08:53:27

After running around unproductively to and using several codes that didn't work. This is what worked for me on vertical scroll visibility using Jquery. Replce '#footerplace' with the element you'd like to track vertically.

jQuery.expr.filters.offscreen = function(el) {
  var rect = el.getBoundingClientRect();
  console.log(rect)
  console.log('window height', $(window).height());

  return (
           (rect.top <= $(window).height()) && (rect.bottom <= $(window).height())
         );
};
$(document).scroll(function(){
    if ($('#footerplace').is(':offscreen')){
      console.log('this is true');
    $('#footerplace').is(':offscreen');
    } else {
     console.log('this is false');
    $('#footerplace').is(':offscreen');

    }

@John Doherty 2017-09-11 23:15:32

A more efficient version of this answer:

 /**
 * Is element within visible region of a scrollable container
 * @param {HTMLElement} el - element to test
 * @returns {boolean} true if within visible region, otherwise false
 */
 function isScrolledIntoView(el) {
      var rect = el.getBoundingClientRect();
      return (rect.top >= 0) && (rect.bottom <= window.innerHeight);
 }

@Bryan 2017-05-30 19:31:11

Javascript only :)

function isInViewport(element) {
  var rect = element.getBoundingClientRect();
  var html = document.documentElement;
  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= (window.innerHeight || html.clientHeight) &&
    rect.right <= (window.innerWidth || html.clientWidth)
  );
}

@Vandolph Reyes 2017-12-25 04:15:40

Where does getBoundingClientRect came from?

@rpearce 2017-03-14 03:20:51

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

@Domysee 2016-06-26 13:35:40

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.

@mr1031011 2018-02-13 11:41:09

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?

@Domysee 2018-02-13 13:59:47

@mr1031011 It should be possible to add the handler to window and then check for the target to identify the container that was scrolled.

@vanowm 2018-02-17 19:02:24

@mr1031011 2018-10-26 17:31:33

right, it doesn't work with the example given by @vanowm,

@Scott Dowding 2009-01-28 15:36:57

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');
}

@Andrew B. 2013-02-12 20:29:09

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.

@Jürgen Paul 2013-09-09 18:48:05

how to add a little offset?

@Christian Schnorr 2014-01-17 14:30:22

Only worked when I used window.innerHeight instead

@Sarah Vessels 2014-01-26 17:18:41

For elemTop I used $(elem).position().top and for elemBottom I used elemTop + $(elem).outerHeight(true).

@Sarah Vessels 2014-01-26 17:28:01

Also, using && tests if the entire element is in view. If you want to know whether any part of the element is in view, use ||.

@bravedick 2014-03-18 13:32:11

Added the same method in Vanilla: stackoverflow.com/a/22480938/643514

@Jerad 2014-03-20 19:36:02

Thanks for the addition, @SarahVessels! This worked for me.

@TrippinBilly 2014-06-07 03:07:20

As of 06/06/2014, I just could not get this to work properly for Firefox 29. "$(elem).offset().top" will constantly return a static result, always the same even after scrolling. I ended up finding a solution that uses the vanilla javascript method getBoundingClientRect()

@Grizly 2014-07-29 23:42:21

For: "Any part of the element in view", I used: ((( elemTop >= docViewTop) && (elemTop <= docViewBottom)) || ((elemBottom >= docViewTop) && (elemBottom <= docViewBottom)))

@Sagiv Ofek 2014-12-17 22:41:03

i found combining two options works best - return ((elemBottom >= docViewBottom) && (elemTop <= docViewTop)) || ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));

@CodeMoose 2015-05-13 19:55:54

For "any part of element in view", ((elemTop <= docViewBottom) && (elemBottom >= docViewTop)) covers all cases completely - even if the top and bottom edges are offscreen and only the middle is in view.

@jorar91 2015-09-30 20:40:50

For "any part of element in view" Math.min(elemBottom, docViewBottom) >= Math.max(elemeTop, docViewTop);.

@gcampbell 2016-06-06 19:39:39

@GauravAggarwal This answer is jQuery.

@Jordan 2016-08-01 19:56:44

This code works! You can even replace $(window) with $(element).scrollParent() from jQuery UI, and this works with scrollable elements (i.e., overflow-y:scroll) as well.

@user2934433 2017-03-18 21:51:51

This is not working when I consider event.target as $(window). I have <div id="scrollable"> <table> </table> <div id = "tobeInview"> </div> </div>

@Antonio Sesto 2018-02-16 08:08:17

It does not seem to work in all cases. For example, even after I scrolled to the very bottom of the windows, I get this: docViewTop: 496, docViewBottom: 1039, elemTop: 1029.3125, elemBottom: 1039.3125 and the function returns false (= it is not visible).

@Cerin 2018-06-14 20:06:36

This doesn't work with floating elements. It doesn't take into account the element's absolute position, and incorrectly thinks its scrolled offscreen when it hasn't.

@WebWanderer 2016-09-26 17:35:43

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!

@Domysee 2017-04-05 14:03:09

Very nice explanation! But there are already answers that do exactly what you do, like Ally's answer

@WebWanderer 2017-04-06 04:21:59

@Domysee Hmm, I somehow skipped over that. Fair enough. Thank you for pointing that out though. It is nice to see this done another way.

@pie6k 2015-02-22 23:33:30

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.

@vsync 2018-02-06 12:21:23

The use of expr for checking an element's scroll visibility has a huge disadvantage since it may only work for elements which are not inside scroll containers themselves, because you are using the window object as the hard-coded scope.

@user3491125 2016-06-14 11:04:16

Made a simple plugin detecting if element is visible within a scrollable container

    $.fn.isVisible = function(){

      var win;
      if(!arguments[0])
      {
        console.error('Specify a target;');
        return false;
      }
      else
      {
        win = $(arguments[0]);
      }
      var viewport = {};
      var bounds = this.offset();
      bounds.right = bounds.left + this.outerWidth();
      bounds.bottom = bounds.top + this.outerHeight();
      viewport.bottom = win.height() + win.offset().top;
      return (!( bounds.top > viewport.bottom) && (win.offset().top < bounds.bottom));
    };

Call it like this $('elem_to_check').isVisible('scrollable_container');

Hope it'll help.

@webicy 2014-04-29 10:24:51

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

@Meetai.com 2014-07-06 06:58:27

This works for me, but I used the, seemingly more complete, function isScrolledIntoView at stackoverflow.com/questions/487073/… :)

@Young 2015-04-07 22:23:02

I think it should be $(window).scrollTop() < $(elem).offset().top + $(elem).height() ;

@bubencode 2018-09-02 21:06:10

My modification would be like this: ` return $( window ).scrollTop() + $( window ).height() > $( elem ).offset().top + $( elem ).height(); `

@Sonny Lloyd 2015-08-19 15:51:40

I was looking for a way to see if the element is going to come into view soon, so by extending the snippets above i managed to do it. thought i would leave this here just in case it will help someone

elm = is the element you want to check is in the view

scrollElement = you can pass window or a parent element that has a scroll

offset = if you want it to fire when the element is 200px away before its in the screen then pass 200

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

@willsquire 2015-05-04 21:39:42

Checks if the element is on screen at all, rather than the accepted answer's approach that checks if the div is entirely on the screen (which won't work if div is bigger than the screen). In pure Javascript:

/**
 * Checks if element is on the screen (Y axis only), returning true
 * even if the element is only partially on screen.
 *
 * @param element
 * @returns {boolean}
 */
function isOnScreenY(element) {
    var screen_top_position = window.scrollY;
    var screen_bottom_position = screen_top_position + window.innerHeight;

    var element_top_position = element.offsetTop;
    var element_bottom_position = element_top_position + element.offsetHeight;

    return (inRange(element_top_position, screen_top_position, screen_bottom_position)
    || inRange(element_bottom_position, screen_top_position, screen_bottom_position));
}

/**
 * Checks if x is in range (in-between) the
 * value of a and b (in that order). Also returns true
 * if equal to either value.
 *
 * @param x
 * @param a
 * @param b
 * @returns {boolean}
 */
function inRange(x, a, b) {
    return (x >= a && x <= b);
}

@Click Upvote 2015-04-18 12:15:33

The only plugin which works consistently for me for doing this, is: https://github.com/customd/jquery-visible

I ported this plugin to GWT recently since I didn't want to add jquery as a dependency just for using the plugin. Here's my (simple) port (just including the functionality that I need for my use case):

public static boolean isVisible(Element e)
{
    //vp = viewPort, b = bottom, l = left, t = top, r = right
    int vpWidth   = Window.getClientWidth();
    int vpHeight = Window.getClientHeight();


    boolean tViz = ( e.getAbsoluteTop() >= 0 && e.getAbsoluteTop()<  vpHeight);
    boolean bViz = (e.getAbsoluteBottom() >  0 && e.getAbsoluteBottom() <= vpHeight);
    boolean lViz = (e.getAbsoluteLeft() >= 0 && e.getAbsoluteLeft() < vpWidth);
    boolean rViz = (e.getAbsoluteRight()  >  0 && e.getAbsoluteRight()  <= vpWidth);

    boolean vVisible   = tViz && bViz;
    boolean hVisible   = lViz && rViz;

    return hVisible && vVisible;
}

@Brendan Nee 2015-04-17 23:22:40

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;
}

@hashchange 2015-03-05 17:02:36

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.

@Vasuki Dileep 2015-03-04 11:34:51

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;
}

@Lorenz Lo Sauer 2015-01-23 11:50:53

I adapted this short jQuery function extension, which you can feel free to use (MIT licence).

/**
 * returns true if an element is visible, with decent performance
 * @param [scope] scope of the render-window instance; default: window
 * @returns {boolean}
 */
jQuery.fn.isOnScreen = function(scope){
    var element = this;
    if(!element){
        return;
    }
    var target = $(element);
    if(target.is(':visible') == false){
        return false;
    }
    scope = $(scope || window);
    var top = scope.scrollTop();
    var bot = top + scope.height();
    var elTop = target.offset().top;
    var elBot = elTop + target.height();

    return ((elBot <= bot) && (elTop >= top));
};

@Brent Barbata 2014-12-30 01:54:05

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

@Derrick J Wippler 2014-09-10 20:41:18

Simple modification for scrollable div (container)

var isScrolledIntoView = function(elem, container) {
    var containerHeight = $(container).height();
    var elemTop = $(elem).position().top;
    var elemBottom = elemTop + $(elem).height();
    return (elemBottom > 0 && elemTop < containerHeight);
}

NOTE: this does not work if the element is larger than the scrollable div.

@Rafael Garcia 2014-08-15 14:23:50

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;
}

@Pigmalión 2013-04-25 09:33:18

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 2014-06-21 01:10:21

this works for me if I change the e.style.opacity > 0 to (!e.style.opacity || e.style.opacity > 0) because by default it is the empty string for me in FF.

@bmlkc 2014-06-14 20:59:43

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

@Adrian P. 2014-02-15 18:51:09

Here is another solution from http://web-profile.com.ua/

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

@Cromwell 2018-10-15 08:57:32

best solution for me, so far. does the job very well and simple.

@Simon Price 2018-11-07 15:19:55

outstanding!!! will see how I can use this as its much better than anything ive seen

@Robert 2013-10-23 17:30:40

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 demo here: http://jsfiddle.net/RRSmQ/

Related Questions

Sponsored Content

55 Answered Questions

[SOLVED] How do I check if an element is hidden in jQuery?

61 Answered Questions

[SOLVED] How to check whether a checkbox is checked in jQuery?

3 Answered Questions

58 Answered Questions

[SOLVED] How do I redirect to another webpage?

79 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 5836354 View
  • 7279 Score
  • 79 Answer
  • Tags:   javascript arrays

29 Answered Questions

[SOLVED] jQuery scroll to element

  • 2011-07-13 09:49:44
  • DiegoP.
  • 2258397 View
  • 2119 Score
  • 29 Answer
  • Tags:   javascript jquery

22 Answered Questions

[SOLVED] Check if a user has scrolled to the bottom

23 Answered Questions

[SOLVED] Event binding on dynamically created elements?

40 Answered Questions

[SOLVED] Setting "checked" for a checkbox with jQuery?

15 Answered Questions

[SOLVED] "Thinking in AngularJS" if I have a jQuery background?

Sponsored Content