<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);
}

External CSS

  1. https://codepen.io/tutsplus/pen/vYrpEwd.css

External JavaScript

This Pen doesn't use any external JavaScript resources.