Guide

Scroll animations with plain CSS and a few lines of JavaScript

How to fade, slide or zoom elements in as they scroll into view without an animation library, and how to respect visitors who prefer less motion.

Quick answer: hide the element with a class, watch it with an IntersectionObserver, and add a second class when it enters the screen so a CSS transition plays. No library needed, and it stays fast if you animate only opacity and transform.

The pattern

.reveal { opacity: 0; transform: translateY(24px);
  transition: opacity .6s ease, transform .6s ease; }
.reveal.is-in { opacity: 1; transform: none; }
const io = new IntersectionObserver((entries) => {
  entries.forEach((e) => {
    if (e.isIntersecting) { e.target.classList.add('is-in'); io.unobserve(e.target); }
  });
}, { threshold: 0.15 });
document.querySelectorAll('.reveal').forEach((el) => io.observe(el));

The observer fires once when the element is 15% visible, adds the class and stops watching it, so there is nothing running afterwards.

Keep it smooth

Respect reduced motion

Some visitors turn on a system setting because motion makes them ill. Honour it:

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

Do not hide content without a fallback

If the script fails, elements marked .reveal stay invisible. Add the hidden style only when JavaScript is running, for example by setting a class on html first.

Let a tool write it

The animate-on-scroll generator lets you pick an effect, set duration, delay and easing, preview it and copy the CSS and script. The easing editor helps you tune the curve, and the effects library lets you browse 20 ready-made animations.