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