Lenis を使って慣性(スムース)スクロールを実装する

Created on

Lenis は慣性スクロールを実現するための JavaScript ライブラリ。

まずはインストール。 ※CDN でも利用可能

pnpm add lenis

そしてスクリプトファイルでインポート。

import Lenis from 'lenis'

オプションを指定してインスタンス化。

const lenis = new Lenis({
  autoRaf: true,
});

autoRafrequestAnimationFrame ループを自動的に実行するかどうかを表す。

raf ループをカスタマイズすることがない場合はこのオプションを true にしておく。GSAP の ScrollTrigger を併用する場合などはこのオプションは不要になる。

次に、推奨の CSS を追加する。パッケージに含まれているものをインポートすることもできる。

html.lenis,
html.lenis body {
  height: auto;
}
 
.lenis:not(.lenis-autoToggle).lenis-stopped {
  overflow: clip;
}
 
.lenis [data-lenis-prevent],
.lenis [data-lenis-prevent-wheel],
.lenis [data-lenis-prevent-touch] {
  overscroll-behavior: contain;
}
 
.lenis.lenis-smooth iframe {
  pointer-events: none;
}
 
.lenis.lenis-autoToggle {
  transition-property: overflow;
  transition-duration: 1ms;
  transition-behavior: allow-discrete;
}

基本的にはこれだけで慣性スクロールが実現できる。

オプションの簡単な紹介

Lenis はデフォルトでいい感じのスムーススクロールになるが、オプションの値を変更することで挙動を微調整することができる。冒頭で紹介した autoRaf 以外にもさまざまなオプションがある。

ここでは次の4つのオプションを紹介する。

  • lerp
  • duration
  • easing
  • infinite

lerp

作成するサイトやアプリケーションによっては、デフォルトの慣性スクロールがちょっとスムース過ぎるみたいなケースもある。その場合は lerp オプションの値を変更するとよい。

lerp は linear interpolation の略。慣性の具合を調整するための係数みたいなもの。 0 から 1 の値を指定することができて、デフォルトは 0.1 になっている。それ以上の値にすることでスムース感を抑えられる。

ちなみに、0.1 より下の値(e.g. 0.05)だと慣性が効きすぎている感があって逆に使いづらい感じになる。

duration

lerp を使わない場合、スクロールアニメーションの時間を指定することも可能。この場合は、指定したイージングによってスクロールをなめらかにできる。

easing

lerp を使わない場合のイージング関数を指定できる。デフォルトでは (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)) になっている。

infinite

infinitetrue にすることで無限スクロールを実現できる。あまり使うことはなさそうだが、おもしろいオプション。

GSAP の ScrollTrigger と併用する

GSAP の ScrollTrigger と Lenis を併用する場合は、ドキュメントにある通り次の記述が必要になる。 Lenis インスタンス化時に autoRaf を指定していないことに注意。

// Initialize a new Lenis instance for smooth scrolling
const lenis = new Lenis();
 
// Synchronize Lenis scrolling with GSAP's ScrollTrigger plugin
lenis.on('scroll', ScrollTrigger.update);
 
// Add Lenis's requestAnimationFrame (raf) method to GSAP's ticker
// This ensures Lenis's smooth scroll animation updates on each GSAP tick
gsap.ticker.add((time) => {
  lenis.raf(time * 1000); // Convert time from seconds to milliseconds
});
 
// Disable lag smoothing in GSAP to prevent any delay in scroll animations
gsap.ticker.lagSmoothing(0);

参考