Css3-Animate Elements If Visible in Viewport (Page Scroll)

CSS3-Animate elements if visible in viewport (Page Scroll)

Using IntersectionObserver API

The IntersectionObserver API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport.

Here's an example that triggers a classList toggle when an Element is in viewport:

const inViewport = (entries, observer) => {
entries.forEach(entry => {
entry.target.classList.toggle("is-inViewport", entry.isIntersecting);
});
};

const Obs = new IntersectionObserver(inViewport);
const obsOptions = {}; //See: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_options

// Attach observer to every [data-inviewport] element:
const ELs_inViewport = document.querySelectorAll('[data-inviewport]');
ELs_inViewport.forEach(EL => {
Obs.observe(EL, obsOptions);
});
[data-inviewport] { /* THIS DEMO ONLY */
width:100px; height:100px; background:#0bf; margin: 150vh 0;
}

/* inViewport */

[data-inviewport="scale-in"] {
transition: 2s;
transform: scale(0.1);
}
[data-inviewport="scale-in"].is-inViewport {
transform: scale(1);
}

[data-inviewport="fade-rotate"] {
transition: 2s;
opacity: 0;
}
[data-inviewport="fade-rotate"].is-inViewport {
transform: rotate(180deg);
opacity: 1;
}
Scroll down...
<div data-inviewport="scale-in"></div>
<div data-inviewport="fade-rotate"></div>

Activate CSS Animation when visible

You could put the animation in a separate class, and add this class when the element is scrolled into view.

This can be done with jQuery by adding a custom function that detects when the element is in view, and trigger this function every time the user scrolls.

// function to detect if an element is scrolled into view
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));
};

// listen for scroll event
$(window).scroll(function () {
// check if element is scrolled into view
if (isScrolledIntoView($('#animated_text'))) {
// element is scrolled into view, add animation class
$('#animated_text').addClass('animation');
}
});
.pcb-text {
display: flex;
justify-content: center;
align-items: center;
}

.pcb-text p {
font-size: 35px;

overflow: hidden;
white-space: nowrap;
margin: 0 auto;
border-right: .12em solid orange;
}

/* move animation to separate class */
.animation p {
animation: typing 2s steps(45),
blink-caret 0.85s step-end infinite;
}

@keyframes typing {
from {
width: 0;
}
to {
width: 100%;
}
}

/* The typewriter cursor effect */

@keyframes blink-caret {
from,
to {
border-color: transparent
}
50% {
border-color: orange;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div style="height: 1000px"></div>
<div class="pcb-text" id="animated_text">
<div class="text-center">
<p>Some Text Here</p>
</div>
</div>

Activate CSS3 animation when the content scrolls into view

Capture scroll events

This requires using JavaScript or jQuery to capture scroll events, checking each time a scroll event fires to see if the element is in view.

Once the element is in view, start the animation. In the code below, this is done by adding a "start" class to the element, that triggers the animation.

Updated demo

HTML

<div class="bar">
<div class="level eighty">80%</div>
</div>

CSS

.eighty.start {
width: 0px;
background: #aae0aa;
-webkit-animation: eighty 2s ease-out forwards;
-moz-animation: eighty 2s ease-out forwards;
-ms-animation: eighty 2s ease-out forwards;
-o-animation: eighty 2s ease-out forwards;
animation: eighty 2s ease-out forwards;
}

jQuery

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();
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 = $('.bar .level');

// If the animation has already been started
if ($elem.hasClass('start')) return;

if (isElementInViewport($elem)) {
// Start the animation
$elem.addClass('start');
}
}

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

Play animation when content get into view

This can be very easily done using little jquery. All you need to do is listen to the scroll event, then check if user have scrolled to the target element. If the user did, then add animation class from your animate.css. Adjust your if condition according to your desires. Check the below code and fiddle https://jsfiddle.net/15z6x5ko/ for reference

$(document).ready(function(){
$(document).scroll(function(evt){
var v2 = Math.abs($('.box').position().top - $(window).height()/2);
var v1 = $(this).scrollTop();
if( v1 > v2 ){
console.log('in');
$('.box').addClass('animated flip')
}
});
});

So as per your request, let me try to explain the code line by line

$(document).ready(function(){

This is easy to understand. It just waits for browser to load all HTML & CSS first and when everything is loaded, the javascript code inside this function will run.

$(document).scroll(function(evt){

This is an event handler, our callback function will run whenever user scrolls on document. Remember change $(document) according whatever the parent is of your target element. So if your target div is inside another div whose class is .parent then use $('.parent').scroll . As for my code I am listening the event on document. When my document scrolls, my event will trigger.

var v1 = $(this).scrollTop();

This code will get the amount of scrolling user had done in pixels.

var v2 = Math.abs($('.box').position().top - $(window).height()/2);

This is a simple math that checks the position of my target div from its parent element subtracting the half of the size of window from it. This will return the pixel positing of your target div. So when user reaches this pixel positing while scrolling, your animation will start.

$('.box').addClass('animated flip')

Now this code simply adds the animation css classes into the target div as soon as user scrolls to the target div.

Animate.css: trigger animation when becoming visible while scrolling

@Mohammed animate-dynamic solution use jQuery.

This one instead is a simple solution in vanilla JS using Animate.css, Waypoints and a few lines of css:

javascript:

//https://stackoverflow.com/a/74810616/3929620
//https://stackoverflow.com/a/32677672/3929620
//https://stackoverflow.com/a/69614783/3929620
const animateList = [].slice.call(document.querySelectorAll('.__animate__animated'))
animateList.map(function (animateEl) {
new Waypoint({
element: animateEl,
offset: 'bottom-in-view',
handler: function(direction) {
animateEl.classList.replace('__animate__animated', 'animate__animated')
animateEl.classList.replace('__animate__fadeIn', 'animate__fadeIn')
this.destroy()
},
})
})

css:

.__animate__animated.__animate__fadeIn {
opacity: 0;
}

html:

<div class="__animate__animated __animate__fadeIn">
<!-- your code here -->
</div>

Any improvement is welcome! ;)

Start animation when scrolled into view

You need to use Intersection Observer API. Basically a class is added only when the bar starts to be visible (in the exemple below I've named this class animate).
I've added in your HTML code a placeholder to simule the content before the bars and move animation-name: example from .bara1 to .bara1.animate

const observer = new IntersectionObserver(intersections => {
intersections.forEach(({
target,
isIntersecting
}) => {
target.classList.toggle('animate', isIntersecting);
});
}, {
threshold: 0
});

document.querySelectorAll('.bara1').forEach(div => {
observer.observe(div);
});
#placeholder {
height: 100vh;
display: grid;
place-items: center;
font-size: 2rem;
border: 1px solid;
}

@keyframes example {
0% {
width: 0%;
}

10% {
width: 0%;
}

100% {
max-width: 100%;
}
}

.bara1 {
border-radius: 1px 25px 25px 1px;
padding: 16px;
background-color: #7ac1cf;
position: relative;
margin-bottom: -32px;
z-index: 2;
animation-duration: 6s;
}

.bara1.animate {
animation-name: example;
}

.barb1 {
border-radius: 1px 25px 25px 1px;
padding: 16px;
background-color: #e3e3e3;
position: relative;
margin-bottom: 8px;
z-index: 1;
}

.textbox {
position: absolute;
color: #ffffff;
margin-top: -12px;
}
<section id="placeholder">This is a placeholder</section>

<div class="bara1" style="width: 92%">
<div class="textbox"><b>text</b>  
<font size="2px" color="#def7fc">92%</font>
</div>
</div>
<div class="barb1"></div>

<div class="bara1" style="width: 78%">
<div class="textbox"><b>text</b>  
<font size="2px" color="#def7fc">78%</font>
</div>
</div>
<div class="barb1"></div>

<div class="bara1" style="width: 56%">
<div class="textbox"><b>text</b>  
<font size="2px" color="#def7fc">56%</font>
</div>
</div>
<div class="barb1"></div>

<div class="bara1" style="width: 40%">
<div class="textbox"><b>text</b>  
<font size="2px" color="#def7fc">40%</font>
</div>
</div>
<div class="barb1"></div>

<div class="bara1" style="width: 31%">
<div class="textbox"><b>text</b>  
<font size="2px" color="#def7fc">31%</font>
</div>
</div>
<div class="barb1"></div>


Related Topics



Leave a reply



Submit