简体   繁体   中英

viewport height difference breaks scroll event

I am looking to add a CSS effect to some columns once they come into the viewport. I took an answer from another SO post: See here . The original files are on wordpress, which I believe doesn't really matter. jQuery works as intended, however, after some troubleshooting it appears that with the answer from the other SO post, the condition of elemTop < viewportBottom never comes true and the event never fires.

<div class="content"></div>
    <div class="wrapper">
      <div class="column first-column">
        <p><strong>title</strong></p>
        <p>lorem.</p>
      </div>
      <div class="column second-column">
        <p><strong>title</strong></p>
        <p>ipsum.</p>
      </div>
      <div class="column third-column">
        <p><strong>title</strong></p>
        <p>dolor.</p>
    </div>
</div>

As far as on codepen, if I set the height of content to height: 84vh; it works perfectly. Anything higher breaks the functionality. My local dev project has different dimensions and doesn't work at all.

Also, I'm working with Chrome. Firefox seems to be working fine if I'm not mistaken.

I've seen various solutions, to include:

  • always showing the parent (parent is never hidden)
  • setting overflow: auto (I'm not sure on which but I've tried setting this on all)
  • having the element in question show from the get-go (this defeats the whole purpose of this in the first place)

None of the above solutions work. Here is my CodePen .

Here is the lengthy JS & CSS:

function isElementInViewport(elem) {
  var $elem = $(elem);
  // Get the scroll position of the page.
  var scrollElem =
    navigator.userAgent.toLowerCase().indexOf("webkit") != -1 ? "body" : "html";
  var viewportTop = $(scrollElem).scrollTop();

  console.log(viewportTop);
  var viewportBottom = viewportTop + $(window).height();

  // Get the position of the element on the page.
  var elemTop = Math.round($elem.offset().top);
  var elemBottom = elemTop + $elem.height();

  return elemTop < viewportBottom && elemBottom > viewportTop;
}

// Check if it's time to start the animation.
function checkAnimation() {
  var $elem = $(".first-column");
  var $elemTwo = $(".second-column");
  var $elemThree = $(".third-column");

  // If the animation has already been started
  if (
    $elem.hasClass("first-column-start") ||
    $elemTwo.hasClass("second-column-start") ||
    $elemThree.hasClass("third-column-start")
  )
    return;

  if (isElementInViewport($elem)) {
    // Start the animation
    $elem.addClass("first-column-start");
    $elemTwo.addClass("second-column-start");
    $elemThree.addClass("third-column-start");
  }
}

// Capture scroll events
$(window).scroll(function() {
  checkAnimation();
});

CSS is only an excerpt:

.wrapper {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.column {
  background: #e2e3e5;
  box-shadow: 0 2px 3px 0 rgba(0, 0, 0, 0.26);
  margin: 0 32px 14px 0;
  max-width: 250px;
  padding: 1rem;
}

@keyframes fadeInLeft {
  from {
    opacity: 0;
    -webkit-transform: translate3d(-20%, 0, 0);
    transform: translate3d(-20%, 0, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes fadeInTop {
  from {
    opacity: 0;
    -webkit-transform: translate3d(0, -20%, 0);
    transform: translate3d(0, -20%, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}
@keyframes fadeInRight {
  from {
    opacity: 0;
    -webkit-transform: translate3d(20%, 0, 0);
    transform: translate3d(20%, 0, 0);
  }
  to {
    opacity: 1;
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }
}

.first-column-start {
  -webkit-animation: fadeInLeft 0.8s;
  -moz-animation: fadeInLeft 0.8s;
  -ms-animation: fadeInLeft 0.8s;
  -o-animation: fadeInLeft 0.8s;
  animation: fadeInLeft 0.8s;
}

.second-column-start {
  -webkit-animation: fadeInTop 0.8s;
  -moz-animation: fadeInTop 0.8s;
  -ms-animation: fadeInTop 0.8s;
  -o-animation: fadeInTop 0.8s;
  animation: fadeInTop 0.8s;
}

.third-column-start {
  -webkit-animation: fadeInRight 0.8s;
  -moz-animation: fadeInRight 0.8s;
  -ms-animation: fadeInRight 0.8s;
  -o-animation: fadeInRight 0.8s;
  animation: fadeInRight 0.8s;
}

How do I make this work? Thank you

I'd use var viewportTop = $(document).scrollTop(); or

var scrollElem = navigator.userAgent.toLowerCase().indexOf("webkit") != -1 ? document : "html";`

"body" does seem to return 0 while scrolling (admittedly I'm unable to provide a proper explanation as to why, right now)

Also, it would be a good idea to maintain references to your queries in Jquery in the outer scope.

var $elem = $(".first-column");
var $elemTwo = $(".second-column");
var $elemThree = $(".third-column");

function isElementInViewport(elem) {
  // Get the scroll position of the page.
  var scrollElem =
    navigator.userAgent.toLowerCase().indexOf("webkit") != -1 ? document : "html";

  var viewportTop = $(scrollElem).scrollTop();

  console.log(viewportTop);
  var viewportBottom = viewportTop + $(window).height();

  // Get the position of the element on the page.
  var elemTop = Math.round($elem.offset().top);
  var elemBottom = elemTop + $elem.height();

  return elemTop < viewportBottom && elemBottom > viewportTop;
}

// Check if it's time to start the animation.
function checkAnimation() {

  // If the animation has already been started
  if (
    $elem.hasClass("first-column-start") ||
    $elemTwo.hasClass("second-column-start") ||
    $elemThree.hasClass("third-column-start")
  )
    return;


  if (isElementInViewport($elem)) {
    console.log("Hi");
    // Start the animation
    $elem.addClass("first-column-start");
    $elemTwo.addClass("second-column-start");
    $elemThree.addClass("third-column-start");
  }
}

// Capture scroll events
$(window).scroll(function() {
  checkAnimation();
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM