



WithCodeMedia-1-pc
WithCodeMedia-2-pc
WithCodeMedia-3-pc
WithCodeMedia-4-pc




WithCodeMedia-1-sp
WithCodeMedia-2-sp
WithCodeMedia-3-sp
WithCodeMedia-4-sp









「アンカーリンクをクリックしたとき、ページがいきなりジャンプして体験が悪い」と感じたことはありませんか? CSSの scroll-behavior: smooth を1行追加するだけで、その問題はほぼ解決します。JavaScriptは不要で、コピペしてすぐ使えます。
この記事では、scroll-behavior の基本的な使い方からアンカーリンクとの組み合わせ方、固定ヘッダーへの対応(scroll-margin-top)、JavaScriptとの使い分け、ブラウザ対応状況、そして「効かない」ときのトラブルシューティングまで、実際に動くコードを使って順番に解説します。
初めてスムーススクロールを実装する方も、「前に実装したけど上手くいかなかった」という方も、この記事を読めばすっきり解決できます。
先に、この記事の結論をまとめます。
スムーススクロールを実装するうえで最初に覚えるべきプロパティが scroll-behavior です。このプロパティには auto(デフォルト・即時移動)と smooth(滑らかに移動)の2つの値があります。
最もシンプルな実装は、html 要素に対して scroll-behavior: smooth を指定することです。これだけで、そのページ上のすべてのアンカーリンク(ページ内 #id へのリンク)が滑らかにスクロールするようになります。
/* ページ全体をスムーススクロールにする */
html {
scroll-behavior: smooth;
}たったこれだけです。外部ライブラリも、JavaScriptも不要。ファイルを1行変更するだけで動作します。
実際にアンカーリンクと組み合わせた場合の最小構成を見てみましょう。ポイントは、リンク先要素に 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行が効いています。
scroll-behavior はどの要素にも指定できます。ただし、動作の範囲が変わるので注意が必要です。
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行だけで実現しているシンプルな実装です。
注意点として、固定ヘッダーがある場合は見出しがヘッダーの下に隠れてしまうことがあります。次のセクションでその対処方法を解説します。
固定ヘッダー(position: fixed のヘッダー)があるサイトでアンカーリンクを使うと、ジャンプした先の見出しがヘッダーの下に隠れてしまう問題がよく発生します。
この問題を解決するのが scroll-margin-top プロパティです。ジャンプ先の要素に scroll-margin-top を設定すると、スクロール位置に余白が加わり、要素が固定ヘッダーと重ならない位置に表示されます。
/* 固定ヘッダーの高さ分だけ余白を確保する */
section[id],
h2[id],
h3[id] {
scroll-margin-top: 80px; /* 固定ヘッダーの高さ */
}80px の部分は固定ヘッダーの高さに合わせます。ヘッダーが 60px なら 60px、80px なら 80px と指定してください。少し大きめ(+10〜20px 程度)に設定すると余裕が生まれて見やすくなります。
<!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-margin-top に似たプロパティとして scroll-padding-top があります。2つの違いを整理しておきましょう。
| プロパティ | 指定する要素 | 用途 |
|---|---|---|
scroll-margin-top | ジャンプ先の要素(子) | その要素ひとつだけに余白を付ける |
scroll-padding-top | スクロールコンテナ(親) | コンテナ全体のスクロールスナップ位置に影響する |
固定ヘッダー対策としては、個別の要素に scroll-margin-top を設定するのが最もコントロールしやすい方法です。すべての要素に同じ値を使う場合は、スクロールコンテナ(html 要素)に scroll-padding-top を一括指定する方法もあります。
CSSの scroll-behavior: smooth と同じことを、JavaScriptの scrollIntoView() メソッドでも実現できます。どちらを使うべきか、整理しておきましょう。
// 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(scroll-behavior) | JavaScript(scrollIntoView) |
|---|---|---|
| 実装の手軽さ | 1行追加するだけ | イベントリスナーやDOM操作が必要 |
| コードの保守性 | 非常にシンプル | ロジックが増えると複雑になる |
| カスタマイズ性 | スクロール速度を細かく制御できない | 独自イージングやコールバック処理が可能 |
| アニメーション後の処理 | スクロール完了の検知が難しい | Promise + then() で完了後の処理が書ける |
| ブラウザ対応 | 主要ブラウザで対応済み(IE非対応) | 同等(IEも behavior は非対応) |
| おすすめの場面 | シンプルなアンカーリンク・ページ内移動 | SPA・ダイナミックな操作・完了検知が必要な場合 |
基本的には CSS の scroll-behavior: smooth を優先的に使うのがおすすめです。 理由は、コードが最小限で済み、保守しやすく、パフォーマンスへの影響も少ないからです。JavaScriptが必要になるのは、「スクロール完了後に何か別の処理を実行したい」「スクロールのイージング(加速・減速の曲線)をカスタマイズしたい」「ReactやVueなどのSPAでプログラムから移動を制御したい」といった場合に限定するのがよいでしょう。
scroll-behavior は現在の主要ブラウザでほぼ問題なく使えます。ただし、いくつか知っておくべき点があります。
| ブラウザ | 対応状況 | 備考 |
|---|---|---|
| Chrome(最新) | 対応 | 問題なし |
| Firefox(最新) | 対応 | 問題なし |
| Safari(最新) | 対応 | iOS Safariも対応済み |
| Edge(最新) | 対応 | 問題なし |
| Internet Explorer | 非対応 | 2022年にサポート終了。現在は考慮不要 |
2026年現在、Internet Explorer はマイクロソフトのサポートが終了しており、ビジネス要件として対応が必要なケースはほぼありません。上記の主要ブラウザで動作することを確認できていれば、実務での使用に問題はないでしょう。
一部のユーザーは、目の疲れや三半規管の問題から、画面上のアニメーションやスクロールアニメーションが苦手な場合があります。OSの「アニメーション軽減」設定を有効にしているユーザーには、スムーススクロールを無効にするのがアクセシビリティ上の配慮として推奨されます。
/* アクセシビリティ:アニメーション軽減設定を尊重する */
@media (prefers-reduced-motion: reduce) {
html {
scroll-behavior: auto; /* スムーススクロールを無効化 */
}
}prefers-reduced-motion: reduce のメディアクエリを追加することで、アニメーション軽減設定のユーザーには即時スクロール、通常のユーザーにはスムーススクロールと使い分けられます。
scroll-behavior: smooth を追加したのに動かないというケースは、いくつかの典型的な原因があります。一つずつ確認していきましょう。
最も多い原因のひとつが、html や body 要素に overflow: hidden が設定されているケースです。この場合、スクロール自体が無効になっているため scroll-behavior も機能しません。
/* 注意:overflow: hidden が設定されているとスムーススクロールが効かない場合がある */
/* 悪い例(スムーススクロールが効かなくなる可能性) */
html, body {
overflow: hidden; /* これがあるとスクロール自体が無効になる */
}
/* 良い例 */
html {
scroll-behavior: smooth;
}
body {
/* overflow は特に指定しない(デフォルトのまま) */
}ブラウザの開発者ツール(DevTools)でページの html や body 要素の Computed スタイルを確認し、overflow の値を調べてみてください。
アンカーリンク <a href="#section1"> を使う場合、リンク先に id="section1" が設定されていないとジャンプ自体が機能しません。スムーススクロール以前の問題なので、まず HTML 構造を確認しましょう。
CSSの詳細度(スペシフィシティ)や読み込み順序の問題で、後から読み込まれるCSSファイルが scroll-behavior: auto を上書きしている可能性があります。開発者ツールの Styles パネルで scroll-behavior の値を確認し、打ち消されていないかチェックしてください。
既存のJavaScriptが addEventListener('click', e => e.preventDefault()) などでリンクのデフォルト動作(ページ内ジャンプ)を無効化している場合、スムーススクロールも動きません。コンソールでエラーが出ていないか確認し、既存スクリプトと競合していないか調べましょう。
比較的古いバージョンのSafariでは scroll-behavior が完全にサポートされていない場合があります。Safari 15.4 以降では対応しているため、対象ユーザーのSafariバージョンを確認しましょう。iOS のバージョンによっては古いSafariが使われているケースもあります。
アンカーリンクでジャンプした先の要素を視覚的にハイライトする場合、CSSの :target 疑似クラスと組み合わせることができます。
/* :target セレクターと組み合わせてスタイルを当てる例 */
section:target {
background-color: #fffde7;
outline: 2px solid #d16176;
outline-offset: 4px;
transition: background-color 0.5s ease;
}アンカーリンクで特定のセクションにジャンプしたとき、そのセクションが一時的にハイライトされるような視覚的フィードバックを加えることができます。ユーザーが「ここに来た」とわかりやすくなります。scroll-behavior: smooth と組み合わせると、滑らかに移動しながら目的のセクションがわかりやすくなります。
A. 一般的には html 要素に付けるのが推奨です。ブラウザによっては body に付けても動作することがありますが、仕様上のスクロールコンテナは html 要素です。html { scroll-behavior: smooth; } と書くのが最も確実です。
A. CSS の scroll-behavior: smooth では、スクロール速度やイージングをCSSだけでカスタマイズすることはできません。速度を細かく制御したい場合は、JavaScriptのライブラリ(例:GSAP)や、scrollTo() に独自のアニメーション処理を組み合わせる方法を使います。
A. はい、適用されます。<a href="#">トップへ</a> や <a href="#top">トップへ</a> のようにアンカーリンクで実装された「ページトップへ戻る」ボタンも、scroll-behavior: smooth の恩恵を受けます。JavaScript で実装した場合は別途 scrollIntoView() や scrollTo({ behavior: 'smooth' }) を設定する必要があります。
A. WordPressの場合、テーマのカスタマイザー「追加CSS」に html { scroll-behavior: smooth; } を追加するだけで動作します。ただし、一部のWordPressテーマやプラグインがJavaScriptでアンカーリンクの動作を上書きしている場合があります。その際は、テーマの設定にスムーススクロールのオプションがないか確認し、競合するスクリプトを無効化する対応が必要になることがあります。
A. CSSの scroll-behavior: smooth 自体はフレームワークに依存しないため、ReactやVue、Next.js などのプロジェクトでも、グローバルCSSに html { scroll-behavior: smooth; } を追加すれば動作します。ただし、Next.jsのルーターや React Router など、クライアントサイドルーティングを使う場合はハッシュリンクの動作が異なることがあります。その場合は react-scroll などのライブラリを検討してください。
CSSの実装テクニックを「レイアウト・装飾・アニメーション・基礎・トラブル解決」の目的別に探せる総まとめページを用意しています。実装で迷ったときの索引としてどうぞ。

副業・フリーランスが主流になっている今こそ、自らのスキルで稼げる人材を目指してみませんか?
未経験でも心配することはありません。初級コースを受講される方の大多数はプログラミング未経験です。まずは無料カウンセリングで、悩みや不安をお聞かせください!
WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。
公式サイト より
今すぐ
無料カウンセリング
を予約!