v2.7 · scrollPin · onEnter / onLeavePinning 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.
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.
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 DOMnpm 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 →
Horizontal snap carousel
Drag or swipe between cards with threshold-based snapping and custom easing. onSnap keeps indicators in sync. 1.3 KB, no carousel library.
Video scrubbing on scroll
Scrub a video frame by frame with scroll position, the Apple product-page effect. scrollVideo binds currentTime to scroll in one call.