Skip to content

moveSmoothScroll

Lenis-style inertial scrolling. Wheel and touch input are intercepted and interpolated toward a target position, and the resulting offset is published as the scrollY signal.

This page calls init() when it opens and destroy() when you leave, so the readout below is the live service driving the page you are scrolling right now. The rest of this site uses native scrolling: smooth scrolling is experimental and changes how wheel and touch input feel.

scrollY()
0px

Service active: no (reduced motion, SSR, or not initialised)

Before you reach for it

  • It is a root singleton.SmoothScrollService is providedIn: 'root', and init() is a no-op while an instance is already running. Using [moveSmoothScroll] on a container after the root has initialised does nothing — and destroying that element tears down the global instance. Pick one: the service at the root, or the directive on one container.
  • It opts out of reduced motion.init() returns early when prefers-reduced-motion is active, since overriding native scroll is disorienting. Never assume it is running.
  • Native scroll events stop firing. Read the scrollY signal instead of window.scroll. moveScroll already does this for you.
app.tsts
import { Component, inject } from '@angular/core';
import { SmoothScrollService } from 'angular-movement';

@Component({ /* ... */ })
export class App {
  constructor() {
    // Lower lerp = smoother and slower. Range 0–1.
    inject(SmoothScrollService).init({ lerp: 0.1 });
  }
}
consuming.tsts
const scroll = inject(SmoothScrollService);

// Reactive position, updated on every RAF tick.
readonly scrollY = scroll.scrollY;

// Native 'scroll' events do NOT fire while smooth scroll drives the page,
// so read this signal instead of listening to window.scroll.
readonly progress = computed(() => this.scrollY() / 1000);

scroll.scrollTo(0);          // animated
scroll.scrollTo(500, true);  // instant
scoped-container.htmlhtml
<!-- Scopes smooth scroll to one scrollable container instead of the page -->
<div moveSmoothScroll [moveSmoothScrollLerp]="0.08"
     style="overflow-y: auto; height: 100vh">
  ...content...
</div>