<div class="container">
<h1>Here's some easy to implement scroll animations</h1>
<p>By using transformations instead of absolute positioning, you can keep using relative positions. Not compatible with IE.</p>
<h2>Fade in animations</h2>
<br>
<div class="box fade-right-desktop fade-up-mobile animation">
<p>Fade right on desktop, fade up on mobile</p>
</div>
<br><br>
<div class="box fade-left-desktop fade-down-mobile animation">
<p>Fade left on desktop, fade down on mobile</p>
</div>
<br><br>
<div class="box fade-down-desktop fade-mobile animation">
<p>Fade down on desktop, simple fade on mobile</p>
</div>
<br><br>
<div class="box fade-up-desktop fade-mobile animation">
<p>Fade up on desktop, simple fade on mobile</p>
</div>
<br><br>
<h2>Grow animations</h2>
<p>These require an empty element, or you could alter the code to use pseudo elements.</p>
<br>
<div class="box-wrapper">
<div class="box-background grow-down-desktop grow-up-mobile animation"></div>
<p>Grow down on desktop, grow up on mobile</p>
</div>
<br><br>
<div class="box-wrapper">
<div class="box-background grow-left-desktop grow-down-mobile animation"></div>
<p>Grow left on desktop, grow down on mobile</p>
</div>
<br><br>
<div class="box-wrapper">
<div class="box-background grow-right-desktop grow-up-mobile animation"></div>
<p>Grow right on desktop, grow up on mobile</p>
</div>
<br><br>
<div class="box-wrapper">
<div class="box-background grow-up-desktop grow-down-mobile animation"></div>
<p>Grow up on desktop, grow down on mobile</p>
</div>
<br><br>
<h2>You can also stagger animations.</h2>
<p>By adding on a transition delay property to each box. Since it doesn't make sense to delay on mobile, it will just fade in.</p>
<div class="boxes-row">
<div class="fade-down-desktop fade-mobile animation">
<div class="card">
<img src="https://picsum.photos/200/300" />
<div class="card-content">
No delay
</div>
</div>
</div>
<div class="fade-up-desktop fade-mobile animation stagger-desktop-1">
<div class="card">
<img src="https://picsum.photos/200/300?random=1" />
<div class="card-content">
Delayed 300ms
</div>
</div>
</div>
<div class="fade-left-desktop fade-mobile animation stagger-desktop-2">
<div class="card">
<img src="https://picsum.photos/200/300?random=2" />
<div class="card-content">
Delayed 600ms
</div>
</div>
</div>
<div class="fade-right-desktop fade-mobile animation stagger-desktop-3">
<div class="card">
<img src="https://picsum.photos/200/300?random=3" />
<div class="card-content">
Delayed 900ms
</div>
</div>
</div>
<div class="fade-up-desktop fade-mobile animation stagger-desktop-4">
<div class="card">
<img src="https://picsum.photos/200/300?random=4" />
<div class="card-content">
Delayed 1200ms
</div>
</div>
</div>
</div>
<br><br>
<h2>And you can combine them to make something interesting.</h2>
<br>
<div class="box-wrapper">
<div class="box-background showcase grow-right-desktop grow-down-mobile animation"></div>
<img class="fade-left-desktop fade-up-mobile animation stagger-desktop-1 showcase" src="https://picsum.photos/400" />
</div>
</div>
/* Animation Code */
.animation {
will-change: transform;
}
@media screen and (min-width: 768px) {
.fade-left-desktop,
.fade-right-desktop {
opacity: 0;
transition: 1500ms all ease-in-out;
}
.fade-left-desktop {
transform: translateX(50px);
}
.fade-right-desktop {
transform: translateX(-50px);
}
.fade-left-desktop.animate,
.fade-right-desktop.animate {
opacity: 1;
transform: translateX(0);
}
.fade-down-desktop,
.fade-up-desktop {
opacity: 0;
transition: 1500ms all ease-in-out;
transform: translateY(50px);
}
.fade-up-desktop {
transform: translateY(50px);
}
.fade-down-desktop {
transform: translateY(-50px);
}
.fade-down-desktop.animate,
.fade-up-desktop.animate {
opacity: 1;
transform: translateY(0);
}
.grow-left-desktop,
.grow-right-desktop {
transform: scaleX(0);
transform-origin: left;
transition: 1200ms all ease-in-out;
}
.grow-left-desktop {
transform-origin: right;
}
.grow-right-desktop {
transform-origin: left;
}
.grow-left-desktop.animate,
.grow-right-desktop.animate {
transform: scaleX(1);
}
.grow-down-desktop,
.grow-up-desktop {
transform: scaleY(0);
transition: 1200ms all ease-in-out;
}
.grow-up-desktop {
transform-origin: bottom;
}
.grow-down-desktop {
transform-origin: top;
}
.grow-down-desktop.animate,
.grow-up-desktop.animate {
transform: scaleY(1);
}
.stagger-desktop-1 {
transition-delay: 300ms;
}
.stagger-desktop-2 {
transition-delay: 600ms;
}
.stagger-desktop-3 {
transition-delay: 900ms;
}
.stagger-desktop-4 {
transition-delay: 1200ms;
}
}
@media screen and (max-width: 767px) {
.fade-down-mobile,
.fade-up-mobile {
opacity: 0;
transition: 1500ms all ease-in-out;
}
.fade-up-mobile {
transform: translateY(50px);
}
.fade-down-mobile {
transform: translateY(-50px);
}
.fade-down-mobile.animate,
.fade-up-mobile.animate {
opacity: 1;
transform: translateY(0);
}
.grow-left-mobile,
.grow-right-mobile {
transform: scaleX(0);
transition: 1200ms all ease-in-out;
}
.grow-left-mobile {
transform-origin: right;
}
.grow-right-mobile {
transform-origin: left;
}
.grow-left-mobile.animate,
.grow-right-mobile.animate {
transform: scaleX(1);
}
.grow-down-mobile,
.grow-up-mobile {
transform: scaleY(0);
transform-origin: top;
transition: 1200ms all ease-in-out;
}
.grow-up-mobile {
transform-origin: bottom;
}
.grow-down-mobile {
transform-origin: top;
}
.grow-down-mobile.animate,
.grow-up-mobile.animate {
transform: scaleY(1);
}
.fade-mobile {
opacity: 0;
transition: 1000ms all ease-in-out;
}
.fade-mobile.animate {
opacity: 1;
}
}
body {
background-color: #defff2;
margin: 0;
padding: 0;
width: 100%;
}
/* Page Styles */
.container {
max-width: 1200px;
width: 100%;
margin: 0 auto;
padding: 2rem 1rem 5rem;
}
.box {
width: 400px;
padding: 3rem;
background-color: #041f1e;
color: #03cea4;
border-radius: 10px;
}
.box-wrapper {
position: relative;
width: 400px;
padding: 3rem;
color: #041f1e;
}
.box-wrapper p {
z-index: 1;
position: relative;
}
.box-wrapper img {
z-index: 1;
position: relative;
border-radius: 10px;
}
.box-background {
background-color: #03cea4;
border-radius: 10px;
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 0;
}
.boxes-row {
margin-top: 3rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.boxes-row > div {
border: 1px solid #fafafa;
border-radius: 10px;
overflow: hidden;
width: 100%;
margin: 0.5rem;
}
.card {
display: flex;
flex-direction: column;
}
.card img {
width: 100%;
height: 200px;
}
.card-content {
background-color: #fff;
padding: 1rem;
}
.box-background.showcase {
width: 400px;
height: 400px;
}
img.showcase {
width: 400px;
height: 400px;
object-fit: cover;
}
@media screen and (max-width: 767px) {
.box,
.box-wrapper {
max-width: 300px;
width: 100%;
margin: 0 auto;
}
.boxes-row {
flex-direction: column;
flex-wrap: wrap;
}
.boxes-row > div {
margin-bottom: 2rem;
width: 100%;
max-width: 300px;
}
}
// Reverted back to non-arrow functions because it would break IE11 completely.
var observer = new IntersectionObserver(
function (entries) {
entries.forEach(function (entry) {
var el = entry.target;
if (entry.isIntersecting) {
el.classList.add("animate");
return;
}
});
},
{ threshold: 0.2 }
);
document.querySelectorAll(".animation").forEach(function (i) {
if (i) {
observer.observe(i);
}
});
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.