CSS の scroll-behavior によるスムーズスクロール
アンカーリンクをクリックして、ページが瞬時にあるセクションへジャンプする動きは、突然すぎる印象を与えます。これはユーザーを混乱させ、読書の流れを妨げ、ページ内ナビゲーションを洗練されていないものに見せてしまいます。解決策はたった 1 つの CSS プロパティ — JavaScript ライブラリは不要です。
重要なポイント
scroll-behavior: smoothという CSS プロパティを使えば、JavaScript なしでアンカーリンクやプログラム的なスクロール API にアニメーションを適用できます。- このプロパティは
bodyではなくhtml要素に適用してください。そうすることで、ビューポートに正しく伝播します。 - ブラウザが制御するイージングや時間は CSS ではカスタマイズできません — 細かな制御が必要な場合のみ JavaScript を使用しましょう。
- 固定ヘッダーがアンカーターゲットを覆ってしまうのを防ぐには、
scroll-margin-topを使用します。 - アクセシビリティの設定を尊重するため、ルールは
prefers-reduced-motion: no-preferenceメディアクエリで囲みましょう。
scroll-behavior とは何か、どう動作するか
scroll-behavior CSS プロパティ は、スクロールがプログラム的にトリガーされたとき — アンカーリンク、ハッシュナビゲーション、または window.scrollTo() や element.scrollIntoView() といった JavaScript のスクロール API を通じて — スクロールコンテナがどのように移動するかを制御します。
このプロパティは 2 つの値を受け付けます:
auto— デフォルト。アニメーションなしで瞬時にスクロールします。smooth— ブラウザが定義したイージング関数と時間を使って、スクロールをアニメーション化します。
重要な注意点が 1 つあります: scroll-behavior は、ユーザーのマウスホイール、トラックパッド、スクロールバーのドラッグによるスクロールには影響しません。アンカーによってトリガーされたスクロールおよびプログラム的なスクロールにのみ適用されます。
イージングと時間は完全にブラウザによって制御されます。CSS だけではこれらをカスタマイズできません。特定の時間やカスタムイージングカーブが必要な場合は、JavaScript ベースのソリューションが必要です。
ページに CSS スムーズスクロールを追加する
ページ全体にスムーズスクロールナビゲーションを有効にするには、scroll-behavior: smooth を html 要素に適用します:
html {
scroll-behavior: smooth;
}
body ではなく html を使用してください。 ルート要素に設定すると、プロパティはビューポートに適用されます。body に設定してもビューポートには伝播せず — これがスムーズスクロールが機能しない場合のよくある原因です。
この 1 つの宣言だけで、すべてのアンカーリンクスクロールが自動的に処理されます。JavaScript も依存関係も不要です。
実用的なユースケース
目次ナビゲーション:
<nav>
<a href="#intro">Introduction</a>
<a href="#usage">Usage</a>
<a href="#examples">Examples</a>
</nav>
トップに戻るボタン:
<a href="#top">↑ Back to top</a>
トップに戻るリンクがページの最上部に着地するように、id="top" を持つ要素がページの先頭に存在することを確認するか、フォールバックとして href="#" を使用してください。どちらのパターンも、html に scroll-behavior: smooth が設定されていればすぐに動作します。
scroll-margin-top で固定ヘッダーに対応する
レイアウトに固定ヘッダーが含まれている場合、アンカーターゲットはその背後に部分的にスクロールしてしまいます。これは scroll-margin-top で修正できます:
:target {
scroll-margin-top: 80px; /* match your header height */
}
より広範な対応のために — 現在の :target ではない要素へのプログラム的スクロールも含めて — このルールをセクション要素自体に直接適用します:
section[id] {
scroll-margin-top: 80px;
}
これにより、ターゲット要素にナビゲートしたときにブラウザが着地する位置がオフセットされます — JavaScript は不要です。
Discover how at OpenReplay.com.
アクセシビリティ: prefers-reduced-motion を尊重する
一部のユーザーは、アニメーション化されたスクロールによって乗り物酔いや前庭系の不快感を経験することがあります。常に prefers-reduced-motion メディアクエリを尊重しましょう:
@media (prefers-reduced-motion: no-preference) {
html {
scroll-behavior: smooth;
}
}
このパターンは、OS 設定でモーションをオプトアウトしていないユーザーに対してのみスムーズスクロールを有効にします。これは、アクセシブルなスクロール UX のための推奨アプローチです。
ブラウザサポート
scroll-behavior はすべてのモダンブラウザで広くサポートされています — Chrome 61+、Firefox 36+、Edge 79+、Safari 15.4+、Opera 48+。グローバルでのサポート率は約 95% で、現在のプロジェクトではポリフィルは不要です。
CSS と JavaScript: どちらを使うべきか?
| ニーズ | 最適なアプローチ |
|---|---|
| シンプルなアンカーリンクスクロール | CSS |
| カスタム時間またはイージング | JavaScript |
| 条件付きまたはロジック駆動のスクロール | JavaScript |
ほとんどのページ内ナビゲーションシナリオ — ドキュメンテーションサイト、ランディングページ、ポートフォリオ — では、CSS で十分かつ望ましい選択です。コード量が少なく、依存関係もなく、ブラウザのネイティブパフォーマンスを活用できます。
クイック実装チェックリスト
- ☐
scroll-behavior: smoothはbodyではなくhtmlに適用する - ☐
prefers-reduced-motion: no-preferenceで囲む - ☐ 固定ヘッダーレイアウト用に
scroll-margin-topを追加する - ☐ アンカーリンクとキーボードナビゲーションをテストする
- ☐ iOS Safari での動作を確認する
まとめ
CSS のスムーズスクロールは、実装コストがほぼゼロでありながら、ページ内ナビゲーションを瞬時にもっと意図的なものに感じさせる改善の 1 つです。適切な場所に配置した 1 つの宣言だけで、JavaScript に触れることなく、現実世界のユースケースの大半をカバーできます。
FAQ
scroll-behavior プロパティは、ビューポートを所有するスクロールコンテナ、すなわち html 要素に設定する必要があります。body に適用しても、その値はビューポートレベルのスクローラーには伝播しないため、アンカーリンクのスクロールはデフォルトの瞬時ジャンプにフォールバックします。ルールを html に移動すれば、スムーズアニメーションが期待通り動作します。
いいえ。アニメーションの時間とイージングカーブは完全にブラウザによって決定され、CSS でカスタマイズすることはできません。デザインで特定の速度やカスタムイージング関数が必要な場合は、window.scrollTo を behavior smooth と組み合わせて使用し、カスタムアニメーションロジックを実装する JavaScript ソリューション、またはタイミングを手動で処理する小さなライブラリが必要になります。
いいえ。このプロパティは、ハッシュリンクのクリック、scrollIntoView の呼び出し、window.scrollTo の実行といった、プログラム的およびアンカーによってトリガーされたスクロールにのみ適用されます。マウスホイール、トラックパッドのジェスチャー、スクロールバーのドラッグ、キーボードの矢印キーによるユーザー起因のスクロールは影響を受けず、ブラウザのネイティブスクロール動作が引き続き使用されます。
ターゲット要素に scroll-margin-top プロパティを使用し、ヘッダーの高さと等しい値を設定します。たとえば、id を持つ section 要素に scroll-margin-top を 80px に設定すると、スクロールの着地位置がオフセットされ、セクションが固定ヘッダーの背後に隠れるのではなく、その下に表示されます。JavaScript や追加のマークアップは必要ありません。
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.