<section class="hero-section">
<h1>Reveal image on scroll ↓</h1>
</section>
<section class="reveal-section">
<section class="scroll">
<figure>
<img src="https://assets.codepen.io/210284/flower-6.jpg" alt="">
</figure>
<p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Voluptatum, dignissimos quo hic repellendus libero tempora perferendis numquam ipsam minus doloribus error quas! Accusantium, obcaecati fugit? Eaque culpa ea maxime consectetur.</p>
</section>
</section>
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond&family=DM+Mono:wght@400;500&display=swap');
html, body {
padding: 0;
margin: 0;
background: #fffaf2;
}
img {
max-width: 100%;
height: 100%;
}
.hero-section {
display: flex;
background: #131212;
align-items: center;
text-align: center;
justify-content: center;
height: 90vh;
}
.hero-section h1 {
font-family: 'Cormorant Garamond', serif;
font-size: 3.5rem;
color: beige;
}
.reveal-section {
max-width: 1400px;
margin: 100px auto;
padding: 0 30px;
}
.reveal-section section + section {
margin-top: 120px;
}
.reveal-section .scroll {
display: grid;
grid-column-gap: 60px;
grid-template-columns: 2fr 1fr;
}
.reveal-section .scroll p {
font-size: 1.6rem;
line-height: 1.5;
}
.reveal-section figure {
box-shadow: -1rem 1rem 3rem -2rem rgba(0, 0, 0, 0.5);
position: relative;
}
.reveal-section figure::before {
content: "";
top: 0;
right: 0;
bottom: 0;
left: 0;
position: absolute;
background: #131212;
transition: clip-path 0.3s;
}
.reveal-section figure img {
display: block;
clip-path: inset(0 100% 0 0);
transition: clip-path 0.6s 0.3s;
}
.reveal-section figure::before {
clip-path: inset(0 0 0 100%);
}
.reveal-section figure.is-animated::before,
.reveal-section figure.is-animated img {
clip-path: inset(0);
}
@media (max-width: 1000px) {
.hero-section span {
display: block;
}
.reveal-section {
margin: 60px auto;
}
.reveal-section section + section {
margin-top: 60px;
}
.reveal-section .scroll {
grid-template-columns: 1fr;
grid-row-gap: 30px;
}
}
const targets = document.querySelectorAll(".reveal-section .scroll figure");
const isAnimated = "is-animated";
const threshold = 0.5;
function callback(entries, observer) {
entries.forEach((entry) => {
const elem = entry.target;
if (entry.intersectionRatio >= threshold) {
elem.classList.add(isAnimated);
} else {
elem.classList.remove(isAnimated);
}
});
}
const observer = new IntersectionObserver(callback, { threshold });
for (const target of targets) {
observer.observe(target);
}
This Pen doesn't use any external JavaScript resources.