Smooth Scroll (lerp)
`<pura-smooth-scroll>` is the signature awwwards move: smoothed whole-page scrolling via interpolation (lerp), in the spirit of Lenis, GSAP ScrollSmoother and Locomotive Scroll. Wrap your page content and wheel, touch and scrollbar input become fluid movement with inertia. The technique is pure progressive enhancement: SSR renders the children in normal flow with native scroll intact; on connect the content becomes a fixed, transform-driven layer, a spacer keeps the document at the real height (so the native scrollbar, keyboard scrolling and assistive tech keep working), and a rAF loop lerps a translate toward the native scroll position. The loop idles when settled, so an unmoving page costs zero frames. `lerp` tunes the inertia, `horizontal` maps the vertical scrollbar to sideways movement, and `scrollTo(target, { offset, duration, easing })` gives you eased programmatic scrolling to a pixel value, selector or element. A `pura-smooth-scroll` event fires each frame while moving with `{ scroll, targetScroll, velocity, progress }`, handy for syncing parallax or progress UI. Reduced motion never activates the effect and the page scrolls natively. Each instance registers in `window.__puraSmoothScrolls` by `data-pura-id` with `{ lerp, horizontal, scrollTo }`, and `data-pura-ss-*` attributes mirror config and live progress. Note: the component is designed to wrap the entire page content, and anchor jumps inside the smoothed layer should go through `scrollTo`.
Preview
<!-- wrap the whole page once; wheel, touch and scrollbar are smoothed -->
<pura-smooth-scroll lerp="0.08" offset="-80">
<header>...</header>
<main>
<section id="work">...</section>
<section id="contact">...</section>
</main>
<footer>...</footer>
</pura-smooth-scroll>
<script type="module">
const ss = document.querySelector("pura-smooth-scroll");
// eased programmatic scroll; offset=-80 (from the attribute) clears the fixed header
document.querySelector("#nav-contact").addEventListener("click", () => {
ss.scrollTo("#contact", { duration: 1400 });
});
</script>
<!-- horizontal scene: the vertical scrollbar drives sideways movement -->
<pura-smooth-scroll horizontal lerp="0.1">
<div style="display: flex; height: 100vh;">
<section style="flex: 0 0 100vw;">One</section>
<section style="flex: 0 0 100vw;">Two</section>
<section style="flex: 0 0 100vw;">Three</section>
</div>
</pura-smooth-scroll> Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
lerp | number | 0.1 | Interpolation factor per frame at 60fps, 0 to 1. Lower is floatier; 1 follows the scrollbar exactly. |
horizontal | boolean | false | Map the vertical scrollbar and wheel to horizontal movement of the content. |
duration | number | 1000 | Default duration in milliseconds for programmatic scrollTo(). |
offset | number | 0 | Default pixel offset applied by scrollTo(); negative stops short of the target, e.g. for a fixed header. |
disabled | boolean | false | Keep native scrolling, no smoothing. Toggle at runtime to stop and start the effect. |
Installation
pura is copy-paste and dependency-free. Load the whole library, or just this component.
<link rel="stylesheet" href="/pura/tokens.css">
<script type="module" src="/pura/lib/smooth-scroll.js"></script> import "./pura/lib/smooth-scroll.js";