jQuery - Detecting if element is in viewport

Viewed 24346

I am writing a script that gives different elements some animations when they appear in the screen.

Step one would be to detect when they come in the screen. But that doesn't seem to work.

What I tried:

-The .visible() selector, I quickly found out this does something else in jQuery.

-Different plugins, but I found that they do way more then I need, therefore I decided to write/ find something myself.

-My current script (I found it somewhere in a forum and decided to edit it to my needs) But It works a little strange.

$.fn.isInViewport = function () {
    let elementTop = $(this).offset().top;
    let elementBottom = elementTop + $(this).outerHeight();

    let viewportTop = $(window).scrollTop();
    let viewportBottom = viewportTop + $(window).height();

    return elementBottom > viewportTop && elementTop < viewportBottom;
};

$(window).scroll(function () {
    if ($('.blogcard ').isInViewport()) {
        $(this).addClass("test");
        console.log('success.')
    } else {
        console.log('No success.')
    }
});

Unfortunately this doesn't seem to add a class to my <div class='blogcard'>.

4 Answers

Your use of "this" targets window not .blogcard element:

$(window).scroll(function () {
    if ($('.blogcard ').isInViewport()) {
        //  Use .blogcard instead of this
        $('.blogcard').addClass('test');
        console.log('success.')
    } else {
        //  Remove class
        $('.blogcard').removeClass('test');
        console.log('No success.')
    }
});

You need to get the 'this' context into your $(window).scroll function. I did it by looping through elements, instead of just checking if a .class isInViewport()

$(window).scroll(function () {
   $('.blogcard').each(function(i, el){

      if ($(this).isInViewport()) {
          $(this).addClass('test');
          console.log('content block is in viewport.', $(this))
      } 
   })

});

Removing the class was animating content around too much, so I took that out.

Please try this code ...

$(window).scroll(function () {
    if ($('.section3 ').isInViewport()) {
        $('.section3').addClass('its-now-view');
        alert('sction 3 is now in viewport');
    } else {
        $('.section3').addClass('its-now-view');
       alert('sction 3 is not in viewport');
    }
});
.section{
 height:400px;
}
.section1{
  background-color: #333;
}
.section2{
  background-color: red;
}
.section3{
  background-color: yellow;
}
.section4{
  background-color: green;
}
<html>
<head>
<title>Viewport demo</title>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/is-in-viewport/3.0.4/isInViewport.min.js"></script>
</head>
<body>
<div class="content-wrapper">
<div class="section section1">
  <p>Content of section 1</p>
</div>
<div class="section section2">
  <p>Content of section 2</p>
</div>
<div class="section section3">
  <p>Content of section 3</p>
</div>
<div class="section section4">
  <p>Content of section 4</p>
</div>

</div>

</body>
</html>

For future Googlers. The posted function has a bug, $(window).height() is not providing the viewport height, but rather the entire document height. This isInViewport function returns always true. This is the proper implementation:

$.fn.isInViewport = function () {
  let elementTop = $(this).offset().top;
  let elementBottom = elementTop + $(this).outerHeight();

  let viewportTop = $(window).scrollTop();
  let viewportBottom = viewportTop + window.innerHeight; // <-- here

  return elementBottom > viewportTop && elementTop < viewportBottom;
};
Related