WithCodeMedia-1-pc
previous arrowprevious arrow
next arrownext arrow

WithCodeMedia-1-sp
previous arrowprevious arrow
next arrownext arrow

【2026年版】CSSスムーススクロールの実装方法|scroll-behaviorとアンカーリンクをコピペで滑らかに

「アンカーリンクをクリックしたとき、ページがいきなりジャンプして体験が悪い」と感じたことはありませんか? CSSの scroll-behavior: smooth を1行追加するだけで、その問題はほぼ解決します。JavaScriptは不要で、コピペしてすぐ使えます。

この記事では、scroll-behavior の基本的な使い方からアンカーリンクとの組み合わせ方、固定ヘッダーへの対応(scroll-margin-top)、JavaScriptとの使い分け、ブラウザ対応状況、そして「効かない」ときのトラブルシューティングまで、実際に動くコードを使って順番に解説します。

初めてスムーススクロールを実装する方も、「前に実装したけど上手くいかなかった」という方も、この記事を読めばすっきり解決できます。

先に、この記事の結論をまとめます。

  • scroll-behavior: smooth を html 要素に付けるだけで、ページ全体のアンカーリンクがスムーズになる
  • 固定ヘッダーがある場合は scroll-margin-top をジャンプ先要素に設定すると、コンテンツが隠れない
  • JavaScriptの scrollIntoView({ behavior: ‘smooth’ }) と役割が重なるが、CSSのみで済むなら CSS を優先するとシンプルで保守しやすい
  • アクセシビリティのため prefers-reduced-motion を考慮すると、アニメーション軽減設定のユーザーにも配慮できる
目次

scroll-behavior: smooth の基本

スムーススクロールを実装するうえで最初に覚えるべきプロパティが scroll-behavior です。このプロパティには auto(デフォルト・即時移動)と smooth(滑らかに移動)の2つの値があります。

CSSを1行追加するだけ

最もシンプルな実装は、html 要素に対して scroll-behavior: smooth を指定することです。これだけで、そのページ上のすべてのアンカーリンク(ページ内 #id へのリンク)が滑らかにスクロールするようになります。

/* ページ全体をスムーススクロールにする */
html {
  scroll-behavior: smooth;
}

たったこれだけです。外部ライブラリも、JavaScriptも不要。ファイルを1行変更するだけで動作します。

HTML構造との組み合わせ(最小サンプル)

実際にアンカーリンクと組み合わせた場合の最小構成を見てみましょう。ポイントは、リンク先要素に id 属性を付け、リンク側は href="#id名" と書くことです。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>スムーススクロールのサンプル</title>
  <style>
    html {
      scroll-behavior: smooth;
    }
  </style>
</head>
<body>
  <!-- ナビゲーション -->
  <nav>
    <a href="#section1">セクション1へ</a>
    <a href="#section2">セクション2へ</a>
    <a href="#section3">セクション3へ</a>
  </nav>

  <!-- コンテンツ -->
  <section id="section1">
    <h2>セクション1</h2>
    <p>ここはセクション1の内容です。</p>
  </section>

  <section id="section2">
    <h2>セクション2</h2>
    <p>ここはセクション2の内容です。</p>
  </section>

  <section id="section3">
    <h2>セクション3</h2>
    <p>ここはセクション3の内容です。</p>
  </section>
</body>
</html>

上記のコードをブラウザで開き、ナビゲーションのリンクをクリックすると、画面が滑らかにスクロールして対応するセクションへ移動します。CSSの html { scroll-behavior: smooth; } の1行が効いています。

html要素に付ける場合と特定要素に付ける場合の違い

scroll-behavior はどの要素にも指定できます。ただし、動作の範囲が変わるので注意が必要です。

html要素に指定する場合(ページ全体)

html { scroll-behavior: smooth; } と書くと、ページ全体のスクロールコンテナ(ウィンドウ自体)に対してスムーススクロールが有効になります。通常、ページ内ナビゲーションやページトップへ戻るボタンの実装ではこちらを使います。

特定の要素(スクロールコンテナ)に指定する場合

高さを固定して内部がスクロールする要素(例:サイドバーの目次エリア、モーダル内のリスト)に対してスムーススクロールを適用したい場合は、その要素に直接 scroll-behavior: smooth を指定します。

/* 特定の要素(スクロールコンテナ)にのみ適用 */
.scroll-container {
  scroll-behavior: smooth;
  overflow-y: scroll;
  height: 400px;
}
<div class="scroll-container">
  <div id="item1">アイテム1</div>
  <div id="item2">アイテム2</div>
  <div id="item3">アイテム3</div>
</div>

<!-- コンテナ内へのリンク -->
<a href="#item2">アイテム2へジャンプ</a>

このように、scroll-behavior はスクロールコンテナ(スクロールが発生する要素)に指定するのが基本です。ページ全体のスクロールなら html、特定ボックス内のスクロールならそのボックス要素に指定します。

アンカーリンクと組み合わせる実例(コピペで動く完全コード)

実際のWebサイトで使える構成として、固定ナビゲーション付きの1ページレイアウトを例に、完全なHTMLファイルを紹介します。このコードをそのままコピーしてHTMLファイルとして保存すれば、ブラウザで動作を確認できます。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>アンカーリンク + スムーススクロール</title>
  <style>
    /* スムーススクロール有効化 */
    html {
      scroll-behavior: smooth;
    }

    body {
      font-family: sans-serif;
      margin: 0;
      padding: 0;
    }

    /* 固定ナビゲーション */
    nav {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      background: #333;
      padding: 12px 20px;
      display: flex;
      gap: 20px;
      z-index: 100;
    }

    nav a {
      color: #fff;
      text-decoration: none;
      font-size: 14px;
    }

    nav a:hover {
      text-decoration: underline;
    }

    /* セクション共通 */
    section {
      min-height: 100vh;
      padding: 100px 40px 40px;
      border-bottom: 1px solid #ddd;
    }

    #section1 { background: #f0f8ff; }
    #section2 { background: #fff8f0; }
    #section3 { background: #f0fff0; }
  </style>
</head>
<body>
  <nav>
    <a href="#section1">はじめに</a>
    <a href="#section2">詳細説明</a>
    <a href="#section3">まとめ</a>
  </nav>

  <section id="section1">
    <h2>はじめに</h2>
    <p>このセクションはページの最初の部分です。ナビゲーションのリンクをクリックすると、滑らかにスクロールします。</p>
  </section>

  <section id="section2">
    <h2>詳細説明</h2>
    <p>このセクションは詳細説明のエリアです。scroll-behavior: smooth; を html 要素に付けるだけで動作します。</p>
  </section>

  <section id="section3">
    <h2>まとめ</h2>
    <p>CSSだけで実装できるスムーススクロールは、シンプルで保守しやすい手法です。</p>
  </section>
</body>
</html>

上記のサンプルでは、ナビゲーションバーが画面上部に固定されており、リンクをクリックすると対応するセクションへ滑らかにスクロールします。html { scroll-behavior: smooth; } の1行だけで実現しているシンプルな実装です。

注意点として、固定ヘッダーがある場合は見出しがヘッダーの下に隠れてしまうことがあります。次のセクションでその対処方法を解説します。

scroll-margin-top で固定ヘッダーに隠れないようにする

固定ヘッダー(position: fixed のヘッダー)があるサイトでアンカーリンクを使うと、ジャンプした先の見出しがヘッダーの下に隠れてしまう問題がよく発生します。

この問題を解決するのが scroll-margin-top プロパティです。ジャンプ先の要素に scroll-margin-top を設定すると、スクロール位置に余白が加わり、要素が固定ヘッダーと重ならない位置に表示されます。

scroll-margin-top の書き方

/* 固定ヘッダーの高さ分だけ余白を確保する */
section[id],
h2[id],
h3[id] {
  scroll-margin-top: 80px; /* 固定ヘッダーの高さ */
}

80px の部分は固定ヘッダーの高さに合わせます。ヘッダーが 60px なら 60px80px なら 80px と指定してください。少し大きめ(+10〜20px 程度)に設定すると余裕が生まれて見やすくなります。

固定ヘッダー + scroll-margin-top の完全サンプル

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <style>
    html {
      scroll-behavior: smooth;
    }

    /* 固定ヘッダー */
    header {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      height: 60px;
      background: #d16176;
      display: flex;
      align-items: center;
      padding: 0 20px;
      color: #fff;
      font-weight: bold;
      z-index: 100;
    }

    /* ヘッダーの高さ分スクロール余白を設定 */
    section {
      scroll-margin-top: 60px;
      padding: 40px;
      min-height: 100vh;
      border-bottom: 1px solid #ddd;
    }

    /* ナビゲーション */
    nav {
      margin-top: 60px; /* ヘッダー分下げる */
      padding: 20px;
      background: #f8f8f8;
    }

    nav a {
      margin-right: 16px;
      color: #d16176;
    }
  </style>
</head>
<body>
  <header>サイトロゴ</header>

  <nav>
    <a href="#about">About</a>
    <a href="#service">Service</a>
    <a href="#contact">Contact</a>
  </nav>

  <section id="about">
    <h2>About</h2>
    <p>固定ヘッダーがあっても、scroll-margin-top のおかげで見出しが隠れません。</p>
  </section>

  <section id="service">
    <h2>Service</h2>
    <p>ジャンプ先のセクションが正しい位置に表示されます。</p>
  </section>

  <section id="contact">
    <h2>Contact</h2>
    <p>すべてのセクションで余白が統一されています。</p>
  </section>
</body>
</html>

このサンプルでは、ヘッダーの高さが 60px なので scroll-margin-top: 60px を各セクションに設定しています。ナビゲーションのリンクをクリックすると、ヘッダーの下ぎりぎりから各セクションが始まる位置に滑らかにスクロールします。

scroll-margin-top はアンカーリンクでのスクロール位置にのみ影響し、通常の表示レイアウトには影響を与えません。既存のデザインを崩さずに導入できるのが利点です。

scroll-padding-top との違い(補足)

scroll-margin-top に似たプロパティとして scroll-padding-top があります。2つの違いを整理しておきましょう。

プロパティ指定する要素用途
scroll-margin-topジャンプ先の要素(子)その要素ひとつだけに余白を付ける
scroll-padding-topスクロールコンテナ(親)コンテナ全体のスクロールスナップ位置に影響する

固定ヘッダー対策としては、個別の要素に scroll-margin-top を設定するのが最もコントロールしやすい方法です。すべての要素に同じ値を使う場合は、スクロールコンテナ(html 要素)に scroll-padding-top を一括指定する方法もあります。

JavaScriptのscrollIntoViewとの比較・使い分け

CSSの scroll-behavior: smooth と同じことを、JavaScriptの scrollIntoView() メソッドでも実現できます。どちらを使うべきか、整理しておきましょう。

JavaScriptでの実装例

// JavaScript で同じことをする場合
const target = document.querySelector('#section2');

// behavior: 'smooth' でスムーススクロール
target.scrollIntoView({ behavior: 'smooth', block: 'start' });

// ボタンクリックでジャンプする例
document.querySelector('#btn').addEventListener('click', () => {
  document.querySelector('#target').scrollIntoView({
    behavior: 'smooth',
    block: 'start'
  });
});

scrollIntoView({ behavior: 'smooth', block: 'start' }) を使えば、JavaScriptからでも同様のスムーススクロールが実現できます。ただし、固定ヘッダー対策の scroll-margin-top はJavaScript版でも有効なので、組み合わせて使うことが多いです。

CSS vs JavaScript の使い分け(比較表)

比較項目CSS(scroll-behavior)JavaScript(scrollIntoView)
実装の手軽さ1行追加するだけイベントリスナーやDOM操作が必要
コードの保守性非常にシンプルロジックが増えると複雑になる
カスタマイズ性スクロール速度を細かく制御できない独自イージングやコールバック処理が可能
アニメーション後の処理スクロール完了の検知が難しいPromise + then() で完了後の処理が書ける
ブラウザ対応主要ブラウザで対応済み(IE非対応)同等(IEも behavior は非対応)
おすすめの場面シンプルなアンカーリンク・ページ内移動SPA・ダイナミックな操作・完了検知が必要な場合

基本的には CSS の scroll-behavior: smooth を優先的に使うのがおすすめです。 理由は、コードが最小限で済み、保守しやすく、パフォーマンスへの影響も少ないからです。JavaScriptが必要になるのは、「スクロール完了後に何か別の処理を実行したい」「スクロールのイージング(加速・減速の曲線)をカスタマイズしたい」「ReactやVueなどのSPAでプログラムから移動を制御したい」といった場合に限定するのがよいでしょう。

ブラウザ対応状況と注意点

scroll-behavior は現在の主要ブラウザでほぼ問題なく使えます。ただし、いくつか知っておくべき点があります。

対応状況(2026年7月現在)

ブラウザ対応状況備考
Chrome(最新)対応問題なし
Firefox(最新)対応問題なし
Safari(最新)対応iOS Safariも対応済み
Edge(最新)対応問題なし
Internet Explorer非対応2022年にサポート終了。現在は考慮不要

2026年現在、Internet Explorer はマイクロソフトのサポートが終了しており、ビジネス要件として対応が必要なケースはほぼありません。上記の主要ブラウザで動作することを確認できていれば、実務での使用に問題はないでしょう。

アクセシビリティ:prefers-reduced-motion への対応

一部のユーザーは、目の疲れや三半規管の問題から、画面上のアニメーションやスクロールアニメーションが苦手な場合があります。OSの「アニメーション軽減」設定を有効にしているユーザーには、スムーススクロールを無効にするのがアクセシビリティ上の配慮として推奨されます。

/* アクセシビリティ:アニメーション軽減設定を尊重する */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto; /* スムーススクロールを無効化 */
  }
}

prefers-reduced-motion: reduce のメディアクエリを追加することで、アニメーション軽減設定のユーザーには即時スクロール、通常のユーザーにはスムーススクロールと使い分けられます。

効かない・動かないときのよくある原因と対処法

scroll-behavior: smooth を追加したのに動かないというケースは、いくつかの典型的な原因があります。一つずつ確認していきましょう。

原因1:overflow: hidden や overflow: scroll の設定が影響している

最も多い原因のひとつが、htmlbody 要素に overflow: hidden が設定されているケースです。この場合、スクロール自体が無効になっているため scroll-behavior も機能しません。

/* 注意:overflow: hidden が設定されているとスムーススクロールが効かない場合がある */

/* 悪い例(スムーススクロールが効かなくなる可能性) */
html, body {
  overflow: hidden; /* これがあるとスクロール自体が無効になる */
}

/* 良い例 */
html {
  scroll-behavior: smooth;
}

body {
  /* overflow は特に指定しない(デフォルトのまま) */
}

ブラウザの開発者ツール(DevTools)でページの htmlbody 要素の Computed スタイルを確認し、overflow の値を調べてみてください。

原因2:id 属性がリンク先要素に設定されていない

アンカーリンク <a href="#section1"> を使う場合、リンク先に id="section1" が設定されていないとジャンプ自体が機能しません。スムーススクロール以前の問題なので、まず HTML 構造を確認しましょう。

原因3:scroll-behavior が上書きされている

CSSの詳細度(スペシフィシティ)や読み込み順序の問題で、後から読み込まれるCSSファイルが scroll-behavior: auto を上書きしている可能性があります。開発者ツールの Styles パネルで scroll-behavior の値を確認し、打ち消されていないかチェックしてください。

原因4:JavaScriptがデフォルトの動作を妨げている

既存のJavaScriptが addEventListener('click', e => e.preventDefault()) などでリンクのデフォルト動作(ページ内ジャンプ)を無効化している場合、スムーススクロールも動きません。コンソールでエラーが出ていないか確認し、既存スクリプトと競合していないか調べましょう。

原因5:Safari での動作確認

比較的古いバージョンのSafariでは scroll-behavior が完全にサポートされていない場合があります。Safari 15.4 以降では対応しているため、対象ユーザーのSafariバージョンを確認しましょう。iOS のバージョンによっては古いSafariが使われているケースもあります。

:target セレクターと組み合わせたスタイリング

アンカーリンクでジャンプした先の要素を視覚的にハイライトする場合、CSSの :target 疑似クラスと組み合わせることができます。

/* :target セレクターと組み合わせてスタイルを当てる例 */
section:target {
  background-color: #fffde7;
  outline: 2px solid #d16176;
  outline-offset: 4px;
  transition: background-color 0.5s ease;
}

アンカーリンクで特定のセクションにジャンプしたとき、そのセクションが一時的にハイライトされるような視覚的フィードバックを加えることができます。ユーザーが「ここに来た」とわかりやすくなります。scroll-behavior: smooth と組み合わせると、滑らかに移動しながら目的のセクションがわかりやすくなります。

よくある質問(FAQ)

Q1. scroll-behavior: smooth はbody要素に付ければいいですか?

A. 一般的には html 要素に付けるのが推奨です。ブラウザによっては body に付けても動作することがありますが、仕様上のスクロールコンテナは html 要素です。html { scroll-behavior: smooth; } と書くのが最も確実です。

Q2. スムーススクロールの速度を変えることはできますか?

A. CSS の scroll-behavior: smooth では、スクロール速度やイージングをCSSだけでカスタマイズすることはできません。速度を細かく制御したい場合は、JavaScriptのライブラリ(例:GSAP)や、scrollTo() に独自のアニメーション処理を組み合わせる方法を使います。

Q3. ページトップへ戻るボタンにも適用されますか?

A. はい、適用されます。<a href="#">トップへ</a><a href="#top">トップへ</a> のようにアンカーリンクで実装された「ページトップへ戻る」ボタンも、scroll-behavior: smooth の恩恵を受けます。JavaScript で実装した場合は別途 scrollIntoView()scrollTo({ behavior: 'smooth' }) を設定する必要があります。

Q4. WordPressでスムーススクロールを実装するには?

A. WordPressの場合、テーマのカスタマイザー「追加CSS」に html { scroll-behavior: smooth; } を追加するだけで動作します。ただし、一部のWordPressテーマやプラグインがJavaScriptでアンカーリンクの動作を上書きしている場合があります。その際は、テーマの設定にスムーススクロールのオプションがないか確認し、競合するスクリプトを無効化する対応が必要になることがあります。

Q5. Reactなどのフレームワークでも同じ方法でできますか?

A. CSSの scroll-behavior: smooth 自体はフレームワークに依存しないため、ReactやVue、Next.js などのプロジェクトでも、グローバルCSSに html { scroll-behavior: smooth; } を追加すれば動作します。ただし、Next.jsのルーターや React Router など、クライアントサイドルーティングを使う場合はハッシュリンクの動作が異なることがあります。その場合は react-scroll などのライブラリを検討してください。

関連記事

CSS・Webデザイン実装の総まとめ

CSSの実装テクニックを「レイアウト・装飾・アニメーション・基礎・トラブル解決」の目的別に探せる総まとめページを用意しています。実装で迷ったときの索引としてどうぞ。

WithCodeを体験できる初級コース公開中!

WithCodeを体験できる初級コース公開中!

初級コース(¥49,800)が完全無料に!

  • 期間:1週間
  • 学習内容:
    ロードマップ/基礎知識/環境構築/HTML/CSS/LP・ポートフォリオ作成
    正しい学習方法で「確かな成長」を実感できるカリキュラム。

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?

未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!

この記事を書いた人

WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。

– service –WithGroupの運営サービス

  • WithCode
    - ウィズコード -

    スクール

    「未経験」から
    現場で通用する
    スキルを身に付けよう!

    詳細はこちら
  • WithFree
    - ウィズフリ -

    実案件サポート

    制作会社のサポート下で
    実務経験を積んでいこう!

    詳細はこちら

公式サイト より
今すぐ
無料カウンセリング
予約!

目次