scroll-behavior

ページ内リンクなどで起きるスクロールを、滑らかにするプロパティ。 JavaScriptで少しずつ動かしていたスクロールを、CSSの指定に置き換えられます。

今の書き方

htmlに指定すると、ページ内リンクでもscrollTo()でも、スクロールが滑らかになります。 移動はブラウザに任せるため、URLの#や:targetも、リンク本来のとおりに更新されます。

@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

以前の書き方

ページ内リンクのクリックを止め、JavaScriptでスクロール位置を少しずつ動かしていました。 クリックを止めるため、URLの#は変わらず、:targetも当たりません。

for (const link of document.querySelectorAll('a[href^="#"]')) {
  link.addEventListener('click', (event) => {
    const id = decodeURIComponent(link.hash.slice(1))
    const target = document.getElementById(id)
    if (!target) return
    event.preventDefault()
    const start = window.scrollY
    const distance = target.getBoundingClientRect().top
    const duration = 500
    let startTime
    const step = (time) => {
      if (startTime === undefined) startTime = time
      const progress = Math.min((time - startTime) / duration, 1)
      window.scrollTo(0, start + distance * progress)
      if (progress < 1) requestAnimationFrame(step)
    }
    requestAnimationFrame(step)
  })
}

置き換えるときの注意点

  • htmlに指定します。 bodyに指定しても、ページ全体のスクロールには効きません。
  • 滑らかになるのは、リンクやscrollTo()などで起きるスクロールだけです。 ホイールやキーボードでのスクロールは変わりません。
  • すでにあるscrollTo()やscrollIntoView()も滑らかになり、呼んだ直後はまだ移動先に着いていません。 呼んだ直後にscrollYを読んで使うコードがあれば、動きが変わります。
  • 以前の書き方のコードは、消してから置き換えます。 残したままにすると、1フレームごとのscrollTo()まで滑らかになり、移動が遅れたあとで跳びます。
  • 移動にかかる時間や速さは、ブラウザが決めるため指定できません。 以前の書き方で時間を決めていた場合は、同じ動きにはなりません。 ブラウザがこの指定を無視することも、仕様で認められています。
  • prefers-reduced-motionで囲むのは、OSで動きを減らす設定にしている人には、瞬時に移動させるためです。
  • 固定ヘッダーの下に移動先が隠れる場合は、移動先にscroll-margin-topを指定します。 固定ヘッダーの高さをJavaScriptで引いていた場合は、その計算もCSSに移せます。

フォールバック

未対応のブラウザでは瞬時に移動するだけで、リンクの移動そのものはできます。 対象の5ブラウザはすべて対応済みなので、通常は以前の書き方を残す必要はありません。 古いブラウザでも滑らかさが欠かせない場合だけ、未対応のときに以前の書き方のコードを動かします。

if (
  !('scrollBehavior' in document.documentElement.style) &&
  matchMedia('(prefers-reduced-motion: no-preference)').matches
) {
  // 以前の書き方のコード
}

Browser Support

  • Chrome

    v61+
    2017-09-05
  • Edge

    v79+
    2020-01-15
  • Safari

    v15.4+
    2022-03-14
  • Safari (iOS)

    v15.4+
    2022-03-14
  • Firefox

    v36+
    2015-02-24

機能名やコードで検索できます

例:aspect-ratio、:has()、padding-top

別の言葉や、プロパティ名で試してください

検索を読み込めませんでした