Back to library
INTERACTION_135

Zoom Through Section.

The section scales up and passes the viewer as they scroll. Scaled to 0.85 at 0 opacity before the trigger; scaling past 1.15 while fading out at the top of the range once scroll progress across the section.

CATEGORY
Scroll
COMPLEXITY
Intermediate
TECH
CSS
PLATFORM
Both
PERFORMANCE
Medium
LIVE PLAYGROUND
CSS / CSS
/* Zoom Through Section — The section scales up and passes the viewer as they scroll. */
.zoom-through-section {
  --dur: scroll-linked;
  --ease: linear;
  --stagger: 60ms;
  will-change: transform, opacity;
}

.zoom-through-section > * {
  opacity: 0;
  transform: translateY(14px);
  animation: zoom-through-section-in var(--dur) var(--ease) forwards;
  animation-delay: calc(var(--i, 0) * var(--stagger));
}

/* scaled to 0.85 at 0 opacity -> scaling past 1.15 while fading out at the top of the range */
@keyframes zoom-through-section-in {
  to {
    opacity: 1;
    transform: none;
    filter: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .zoom-through-section > * {
    opacity: 1;
    transform: none;
    animation: none;
  }
}
React / TSX
import { useEffect, useRef } from "react";

/** Zoom Through Section — trigger: scroll progress across the section */
export function ZoomThroughSection({ children }: { children: React.ReactNode }) {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
      el.dataset["state"] = "in";
      return;
    }
    const io = new IntersectionObserver(
      ([entry]) => {
        if (entry?.isIntersecting) {
          el.dataset["state"] = "in";
          io.unobserve(el);
        }
      },
      { threshold: 0.2 },
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);

  return (
    <div ref={ref} className="zoom-through-section" data-state="out">
      {children}
    </div>
  );
}

IF YOU LIKE THIS, STEAL THESE TOO.

INTERACTION_127CSS

Sticky Storytelling Section

A sticky visual holds while the copy beside it advances.

Scroll / LightView
INTERACTION_129CSS + JS

Horizontal Scroll Section

Vertical scrolling drives a horizontal panel track.

Scroll / MediumView
INTERACTION_134CSS

Timeline Progression

A vertical line draws down and reveals each milestone.

Scroll / LightView
INTERACTION_136CSS

Stacked Scroll Panels

Sections stack over one another like cards on a table.

Scroll / LightView