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
How to Abort Image <Img> Load Requests Without Using Window.Stop()
Bootstrap V2 Dropdown Navigation Not Working on Mobile Browsers
How to Detect Supported Video Formats for the HTML5 Video Tag
How to Rotate a Single Object on an HTML 5 Canvas
How to Store a Byte Array in JavaScript
Download Textarea Contents as a File Using Only JavaScript (No Server-Side)
Is It Ok to Add Your Own Attributes to HTML Elements
Embed an External Page Without an Iframe
How to Create a Responsive Image That Also Scales Up in Bootstrap 3
React: How to Load and Render External HTML File
<Script> Tag VS <Script Type = 'Text/Javascript'> Tag
Css3-Animate Elements If Visible in Viewport (Page Scroll)
Removing Page Title and Date When Printing Web Page (With CSS)
How to Convert HTML Table to Excel with Multiple Sheet
Accessing Localstorage from a Webworker