12

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

kalehmann
  • 4,821
  • 6
  • 26
  • 36
mike
  • 445
  • 2
  • 4
  • 18
  • Your logic is missing a couple of scenarios. Try Roko's answer [here](https://stackoverflow.com/a/26831113/519413) – Rory McCrossan Sep 07 '18 at 10:27
  • try to get viewport position range and element position range first? Then, calculate is that element in the range. – Samson Sep 07 '18 at 10:27
  • Use Intersection Observer API to Detect if Element is in Viewport, details here – https://frontendguruji.com/blog/how-to-detect-if-element-is-in-viewport-intersection-observer-api/ – Mandeep Pasbola Mar 06 '23 at 06:05

4 Answers4

11

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.')
    }
});
Roland Ruul
  • 1,172
  • 8
  • 15
  • Thank you, hadn't noticed that. There's still a problem; Now it just gives all `.blogcards` the class test. Even if they are out of the viewport. – mike Sep 07 '18 at 11:13
  • you need to remove the class if they are not in the viewport – jacobdo Sep 07 '18 at 11:15
  • I got Uncaught TypeError: $(...).isInViewport is not a function error, is it my Jquery version? if yes, what version I need to use so I can use this function? Thank you in advance.. – dita Dec 18 '22 at 21:47
2

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.

Corey Bo
  • 371
  • 2
  • 7
1

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>
arvinda kumar
  • 679
  • 8
  • 6
1

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;
};
Newbie
  • 4,462
  • 11
  • 23