縦に長いWebページを上下にスクロールしていると、今どこを見ているのか分からなくなったり、先ほど見た場所へ戻りたくなったりすることがあります。そんなとき、移動先を一覧から選ぶだけで、目的の場所へ移動できると便利です。
今回は、セレクトボックスで移動先を選択すると、ページ内の指定した位置まで滑らかにスクロールする方法を紹介します。複数の移動先を1つの選択欄にまとめられるため、リンクやボタンをいくつも並べる必要がありません。
ページの上の方にいても、下の方にいても、セレクトボックスから目的の場所を選択すれば、対応する位置まで自動的に移動します。選択した項目の値をJavaScriptで取得し、同じIDが設定された場所を移動先として指定します。
デモでは、縦に長いページを想定したスクロール領域にセクション1〜5を配置しています。移動先の上側には20pxの余白を確保し、手動でスクロールすると選択状態が初期化されるため、同じ場所への再移動も可能です。
デモ
通常コンテンツ
スクロール先には指定されていないコンテンツです。下にセクション1〜5が続きます。
セクション1
ここはセクション1です。選択すると、このセクションの位置まで滑らかにスクロールします。
セクション2
ここはセクション2です。スクロール領域内で移動するため、記事全体の表示位置は変わりません。
セクション3
ここはセクション3です。セレクトボックスで選択した値を使って、移動先を指定しています。
セクション4
ここはセクション4です。移動先の上側には20pxの余白を確保しています。
セクション5
ここはセクション5です。下にも通常コンテンツがあるため、この位置までスクロールできます。
通常コンテンツ
スクロール先には指定されていないコンテンツです。実際のWebページにある後続コンテンツやフッターを想定しています。
セレクトボックスからセクション1〜5を選択すると、デモ内のスクロール領域が対応する位置まで滑らかに移動します。選択したセクション名は表示されたままになり、手動でスクロールすると選択状態が初期化されます。各セクションの高さは180px、スクロール領域の高さは400px、移動先の上余白は20pxです。
Q 他のアイコンを使いたい場合はどうするの?
無料のSVGアイコン作成ツールを使って、用途に合ったアイコンを作成できます。
コードをコピーして使おう!
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- 日本語を正しく表示するための文字コード -->
<meta charset="UTF-8">
<!-- PC・タブレット・スマートフォンの画面幅に対応 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ブラウザのタブに表示するページタイトル -->
<title>セレクトボックスで選択した位置へスクロール</title>
<!-- ページのデザインを設定するCSS -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- =========================================
【このサンプルの使い方】
このページは完成済みのサンプルです。
index.htmlをブラウザで開くだけで動作します。
画面上部のセレクトボックスは固定表示されます。
ページを上下にスクロールしても画面内に残るため、
いつでも目的のセクションへ移動できます。
【カスタマイズの手順】
1. 各セクションの見出しや文章を変更します。
2. セレクトボックスの選択肢を変更します。
3. optionのvalueと移動先のidを一致させます。
4. style.cssで横幅・高さ・色などを調整します。
5. 必要に応じてscript.jsで移動先の余白を調整します。
HTMLコメントはブラウザ画面には表示されません。
カスタマイズ後、不要なコメントは削除できます。
========================================= -->
<!-- =========================================
【画面上部に固定するセレクトボックス】
この要素はコンテンツの親要素とは独立しています。
position: fixedで画面上部に固定されるため、
ページをスクロールしても表示され続けます。
固定領域の背景色・高さ・余白などは
style.cssで変更できます。
セレクトボックスの選択肢は下記で変更します。
========================================= -->
<div class="select-scroll_header">
<!-- 固定領域の内容を中央に配置する要素 -->
<div class="select-scroll_header-inner">
<!-- セレクトボックスのラベル -->
<label class="select-scroll_label" for="select-scroll-item">
移動先を選択
</label>
<!-- セレクトボックスとSVG矢印をまとめる要素 -->
<div class="select-scroll_select-wrap">
<!-- =========================================
【カスタマイズ①:選択肢の変更】
optionのvalueは移動先のIDです。
例:
value="section1" → id="section1"へ移動します。
【選択肢の名前を変更する】
「セクション1」を「商品の特徴」など、
好きな文字へ変更できます。
【移動先のIDを変更する】
value="section1"をvalue="features"へ変更したら、
移動先もid="features"へ変更してください。
【選択肢を追加する】
optionを追加し、同じIDを持つ移動先を用意します。
【選択肢を削除する】
不要なoptionを削除します。
最初の「移動先を選択」は初期表示用です。
手動スクロール時にこの表示へ戻るため、
削除しないでください。
========================================= -->
<select class="select-scroll_select" id="select-scroll-item" name="scroll-target">
<option value="" selected disabled>移動先を選択</option>
<option value="section1">セクション1</option>
<option value="section2">セクション2</option>
<option value="section3">セクション3</option>
<option value="section4">セクション4</option>
<option value="section5">セクション5</option>
</select>
<!-- セレクトボックス右端の下向きSVG矢印 -->
<svg class="select-scroll_arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="m5 9 7 7 7-7"></path>
</svg>
</div>
</div>
</div>
<!-- =========================================
【コンテンツの親要素】
この親要素には7つの子要素があります。
子①:IDなし
子②:IDあり(section1)
子③:IDあり(section2)
子④:IDあり(section3)
子⑤:IDあり(section4)
子⑥:IDあり(section5)
子⑦:IDなし
最大横幅は900pxです。
style.cssのmax-widthで変更できます。
子要素の高さ・余白・色もCSSから変更できます。
========================================= -->
<main class="select-scroll_container">
<!-- =========================================
【子①:通常コンテンツ】
この子要素には移動先のIDを設定していません。
ページ上部に表示する通常コンテンツです。
見出しや文章は自由に変更してください。
以下の説明文も削除して構いません。
========================================= -->
<div class="select-scroll_section">
<p class="select-scroll_title">通常コンテンツ</p>
<p class="select-scroll_text">
画面上部のセレクトボックスから移動先を選択すると、指定した位置へ滑らかにスクロールします。
</p>
<p class="select-scroll_text">
ページを上下にスクロールしてもセレクトボックスは画面上部に表示されるため、いつでも目的の場所へ移動できます。
</p>
</div>
<!-- =========================================
【子②:セクション1】
この子要素のIDはsection1です。
セレクトボックス側の
value="section1"と対応しています。
IDを変更する場合は、
optionのvalueも同じ文字列へ変更してください。
見出しや文章は自由に変更できます。
========================================= -->
<section class="select-scroll_section" id="section1">
<p class="select-scroll_title">セクション1</p>
<p class="select-scroll_text">
ここにセクション1の内容を入力してください。
</p>
</section>
<!-- =========================================
【子③:セクション2】
id="section2"とvalue="section2"を一致させます。
IDを変更する場合は両方を変更してください。
見出しや文章は自由に変更できます。
========================================= -->
<section class="select-scroll_section" id="section2">
<p class="select-scroll_title">セクション2</p>
<p class="select-scroll_text">
ここにセクション2の内容を入力してください。
</p>
</section>
<!-- =========================================
【子④:セクション3】
id="section3"とvalue="section3"を一致させます。
IDを変更する場合は両方を変更してください。
見出しや文章は自由に変更できます。
========================================= -->
<section class="select-scroll_section" id="section3">
<p class="select-scroll_title">セクション3</p>
<p class="select-scroll_text">
ここにセクション3の内容を入力してください。
</p>
</section>
<!-- =========================================
【子⑤:セクション4】
id="section4"とvalue="section4"を一致させます。
IDを変更する場合は両方を変更してください。
見出しや文章は自由に変更できます。
========================================= -->
<section class="select-scroll_section" id="section4">
<p class="select-scroll_title">セクション4</p>
<p class="select-scroll_text">
ここにセクション4の内容を入力してください。
</p>
</section>
<!-- =========================================
【子⑥:セクション5】
id="section5"とvalue="section5"を一致させます。
IDを変更する場合は両方を変更してください。
見出しや文章は自由に変更できます。
========================================= -->
<section class="select-scroll_section" id="section5">
<p class="select-scroll_title">セクション5</p>
<p class="select-scroll_text">
ここにセクション5の内容を入力してください。
</p>
</section>
<!-- =========================================
【子⑦:最下部の通常コンテンツ】
この子要素には移動先のIDを設定していません。
高さはstyle.cssで600pxに設定しています。
最下部に十分な高さを確保することで、
セクション5を選択した場合も、
固定セレクトボックスの下側へ
移動先を表示できるようにしています。
高さを変更する場合は、
.select-scroll_section:last-child の
min-heightを変更してください。
この子要素を削除すると、
ページ下部の移動先まで
スクロールできなくなる場合があります。
========================================= -->
<div class="select-scroll_section">
<p class="select-scroll_title">通常コンテンツ</p>
<p class="select-scroll_text">
最下部の通常コンテンツです。
</p>
</div>
</main>
<!-- ページ内スクロール機能のJavaScriptを読み込む -->
<script src="script.js"></script>
</body>
</html>
コードをコピーする場合 使用するコードのタブを選び、「このタブをコピー」をクリックすると、現在表示中のコードをコピーできます。 サンプル一式を取得する場合 HTML・CSSなどすべてのファイルが必要な場合は、「サンプル一式をダウンロード」をクリックしてください。
Q ダウンロードしたけど、これをネット上で動かすにはどうするの?
Googleアカウントがあれば、InfinityFreeで無料サーバーを作成して、ダウンロードしたサンプルをネット上で動かせます。
InfinityFreeを初めて利用する場合は①から、すでにサーバーを作成している場合は②へ進んでください。
ファイル構成と設置方法
このサンプルは、画面上部に固定するセレクトボックスと、移動先となる7つのコンテンツを組み合わせた完成ページです。HTMLで選択肢と移動先を用意し、CSSで固定表示やレイアウトを設定、JavaScriptで選択した位置へのスクロールを制御しています。ZIPには動作確認用のコンテンツも含まれているため、ダウンロード後すぐに動作を確認できます。固定表示は必要に応じて解除でき、通常のページ内スクロールとしても使用できます。
sample/
├── index.html
├── style.css
└── script.js
各ファイルの役割
index.htmlには、セレクトボックスと7つのコンテンツを配置しています。5つの移動先にはそれぞれIDを設定しており、セレクトボックスの選択肢と対応しています。
style.cssでは、セレクトボックスの固定表示、コンテンツの横幅や高さ、背景色、スマートフォンでの余白などを設定しています。固定表示を解除する場合も、このファイルを変更します。
script.jsでは、選択した移動先の取得、固定領域の高さを考慮したスクロール位置の計算、手動スクロール時の選択状態の初期化を行っています。固定表示を解除する場合は、スクロール位置の計算も変更します。
設置方法・使い方
「サンプル一式をダウンロード」からZIPを保存し、展開してください。sampleフォルダ内の3ファイルを同じ階層に配置した状態で、index.htmlをブラウザで開くと動作します。サーバーや外部ライブラリの準備は必要ありません。
初期状態では、ページを上下にスクロールしてもセレクトボックスが画面上部に表示され続けます。「セクション1」から「セクション5」のいずれかを選ぶと、対応するコンテンツへ滑らかに移動します。マウスホイールやタッチ操作などで手動スクロールすると、選択欄は「移動先を選択」に戻ります。
固定表示を解除した場合は、セレクトボックスもコンテンツと一緒にスクロールします。選択した位置へ移動する機能はそのまま使用できますが、セレクトボックスが画面外へ移動すると、再び操作するにはページを上へ戻す必要があります。
セレクトボックスを画面上部に固定する仕組み
style.cssの.select-scroll_headerにposition: fixed;を指定することで、セレクトボックスを含む白い領域全体を画面上部に固定しています。コンテンツは別の親要素に配置しているため、固定領域とは独立してスクロールします。
.select-scroll_header {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 16px 24px;
border-bottom: 1px solid #dbe5f1;
background: #ffffff;
box-sizing: border-box;
z-index: 100;
}
top: 0;は画面の最上部に配置する指定です。z-index: 100;によって通常のコンテンツより手前に表示し、background: #ffffff;で固定領域の背景を白にしています。
固定した領域は通常のページ配置から外れるため、bodyには上側140pxの余白を設定し、最初のコンテンツが固定領域と重ならないようにしています。固定領域の高さを大きく変更した場合は、この上余白も調整してください。
固定表示を解除する場合
セレクトボックスを固定せず、通常のコンテンツと一緒にスクロールさせたい場合は、style.cssの.select-scroll_headerにあるposition: fixed;をposition: static;へ変更します。top: 0;とleft: 0;は不要になるため削除できます。
position: static;
固定を解除すると、セレクトボックスが通常のページ配置に戻ります。そのため、固定領域用に確保していたbodyの上余白も変更します。PC用のpadding: 140px 24px 24px;はpadding: 24px;へ、画面幅640px以下のpadding: 132px 12px 12px;はpadding: 12px;へ変更してください。
また、script.jsでは固定領域の下端位置をスクロール計算から除外します。変更前の計算式にあるfixedBottom -を削除し、次のように変更します。
const position =
target.getBoundingClientRect().top +
window.scrollY -
offset;
これで、固定表示を解除した状態でも選択した移動先へ滑らかにスクロールできます。offsetは移動先と画面上端の間に確保する余白として引き続き使用できます。
なお、固定表示を解除した場合は、最後のコンテンツの高さを600pxにする必要性も低くなります。通常のコンテンツと同じ高さにしたい場合は、.select-scroll_section:last-childのmin-height: 600px;をmin-height: 180px;へ変更できます。ただし、ページ末尾付近の移動先を画面上部まで表示したい場合は、十分なスクロール範囲を確保してください。
選択肢と移動先のIDを対応させる
移動先を変更する場合は、index.htmlのoptionに設定したvalueと、移動先の要素に設定したidを一致させます。例えば、次の組み合わせでは「セクション1」を選ぶとid="section1"の要素へ移動します。
<option value="section1">セクション1</option>
<section class="select-scroll_section" id="section1">
選択肢の表示名は自由に変更できます。「セクション1」を「商品の特徴」に変更しても、valueとidが一致していれば動作します。移動先を追加する場合も、optionと対応するIDを持つ要素を追加するだけで、JavaScript側に個別の移動先を登録する必要はありません。
なお、7つの子要素のうち、最初と最後には移動先のIDを設定していません。現在のサンプルで選択できる移動先は、中央の5つです。固定表示の有無にかかわらず、選択肢とIDの対応方法は変わりません。
固定領域に隠れない位置へスクロールする仕組み
初期状態ではセレクトボックスが画面上部に固定されているため、移動先の先頭を単純に画面上端へ合わせると、見出しが固定領域の裏側に隠れてしまいます。そこでscript.jsでは、固定領域の下端位置を取得し、その高さを考慮して移動先を計算しています。
// 固定領域の画面下端の位置を取得
const fixedBottom = fixedHeader.getBoundingClientRect().bottom;
// 移動先のページ全体での位置を計算する
const position =
target.getBoundingClientRect().top +
window.scrollY -
fixedBottom -
offset;
// 固定領域の下側に余白を確保して滑らかにスクロール
window.scrollTo({
top: Math.max(0, position),
behavior: "smooth"
});
target.getBoundingClientRect().topで移動先の画面内の位置を取得し、window.scrollYを加えてページ全体での位置を求めます。そこから固定領域の下端位置と追加の余白を引くことで、移動先をセレクトボックスの下側に表示します。
追加の余白はscript.jsのconst offset = 20;で設定しています。例えば50に変更すると、固定表示では固定領域の下端から50px、固定を解除した場合は画面上端から50pxの余白を確保できます。behavior: "smooth"は滑らかなスクロールを指定するもので、移動速度はブラウザの動作に依存します。
コンテンツの横幅と高さ
7つの子要素は.select-scroll_containerでまとめており、max-width: 900px;によってPCでの最大横幅を制限しています。各子要素にはmin-height: 180px;を設定し、文章が増えた場合は内容に合わせて高さが広がります。
.select-scroll_container {
width: 100%;
max-width: 900px;
margin: 0 auto;
box-sizing: border-box;
}
最後の子要素だけはmin-height: 600px;に設定しています。これはページ下部にもスクロールできる余地を確保し、「セクション5」を選んだときに移動先を指定した位置へ表示しやすくするためです。固定表示を使用する場合は、固定領域の高さも考慮する必要があります。
固定表示を解除した場合でも、ページ末尾付近の移動先を画面上部へ表示したいときは、最後の子要素の高さを確保しておくと効果的です。
レスポンシブ対応
style.cssでは、固定領域の内容とコンテンツの最大横幅を900pxに揃え、画面が狭い場合はwidth: 100%;で横幅に合わせて縮小します。画面幅640px以下では、ページ左右の余白を24pxから12pxに変更し、固定領域や子要素の内側余白、見出しの文字サイズも調整しています。
固定表示を使用する場合、スマートフォンではbodyの上余白を132pxに変更しています。ラベルやセレクトボックスの高さを変更した場合は、固定領域と最初のコンテンツが重ならないよう、PC用・スマートフォン用の上余白をそれぞれ確認してください。
固定表示を解除する場合は、スマートフォン用のbodyの余白も通常の値に戻すことで、セレクトボックスとコンテンツが自然な順番で表示されます。
コメント