v2.7 · scrollPin · onEnter / onLeave

Sticky pinned section on scroll

Pinning is the pattern behind almost every product walkthrough: an image holds still while copy scrolls past it. Doing it with position: sticky alone breaks down the moment you need to know when the pin started or ended. scrollPin wraps the target in a spacer so nothing shifts, and gives you onEnter, onLeave, onEnterBack and onLeaveBack.

The code

Product image stays pinned while feature descriptions scroll past — the Apple / Stripe product walkthrough pattern. Uses scrollPin with lifecycle callbacks. Scroll inside the preview to see the pin state change.

Hero.tsx
import { scrollPin } from 'svg-scroll-draw/pin';

// Pin the product image while features scroll past
const pin = scrollPin('#product-image', {
  top:         80,           // 80px below top (under a fixed nav)
  pinDistance: window.innerHeight * 3,
  onEnter:     () => image.classList.add('active'),
  onLeave:     () => image.classList.remove('active'),
  onEnterBack: () => image.classList.add('active'),
  onLeaveBack: () => image.classList.remove('active'),
  onProgress:  (p) => progressBar.style.width = p * 100 + '%',
});

// Animate each feature block as it scrolls in
document.querySelectorAll('.feature').forEach(el =>
  scrollAnimate(el, {
    props: { opacity: [0, 1], transform: ['translateY(32px)', 'translateY(0)'] },
    easing: 'ease-out', once: true,
  })
);

// Recalculate after layout change (accordion, content load)
pin.refresh();
pin.destroy(); // removes pin and restores DOM

Live — scroll it

📌
Product Image
Stays fixed →
BEFORE
↑ Scroll the preview to see pin state
One function call
scrollPin wraps the target in a spacer — no layout shift.
Full callbacks
onEnter, onLeave, onEnterBack, onLeaveBack — same as GSAP.
Refresh on resize
Call pin.refresh() after any layout change to recalculate.

Install

terminal
npm i svg-scroll-draw

MIT licensed, zero runtime dependencies. Every API is a separate entry point, so you only ship what you import. Full API reference →