縦スクロールに連動して切り替わるタブを作る方法
ページ内に複数のコンテンツが縦方向に並んでいる場合、現在どの内容を見ているのかをタブで分かりやすく示したいことがあります。縦スクロールに連動するタブを使えば、ページを上下にスクロールしたときに表示位置を判定し、「概要」「特徴」「使い方」など、現在表示しているコンテンツに対応するタブを自動で強調表示できます。
このサンプルでは、HTMLで6つのタブと対応するコンテンツを縦方向に配置し、CSSのposition:stickyを使ってタブを画面上部に固定します。JavaScriptではIntersection Observerを使って縦スクロールによって表示位置に入ったコンテンツを検知し、対応するタブの選択状態を自動で切り替えます。また、タブをクリックすると対応するコンテンツまでスムーズに縦スクロールできるため、スクロール操作とタブ操作のどちらからでも目的の内容へ移動できます。
長いページの目次や商品・サービスの説明、機能紹介、マニュアルなど、複数のコンテンツを上から順番に掲載するページで利用できます。タブ名やコンテンツはHTMLから変更でき、CSSではタブの色・サイズ・余白やコンテンツ部分のデザインなどを調整できます。画面幅が狭い場合は6つのタブを3列2段に並べるレスポンシブ対応も行っています。
免責事項 本コードの利用により発生した損害について、当サイトは一切の責任を負いません。
デモ
スクロールすると、表示位置に合わせて対応するタブが自動で切り替わります。
スクロール位置を検知し、現在表示しているコンテンツに対応するタブを自動で強調表示します。 ページを下へスクロールして、タブの表示が変化することを確認できます。
タブ部分は画面上部に固定されるため、コンテンツをスクロールしても現在位置を確認できます。 表示するセクションが変わると、対応するタブも自動で切り替わります。
タブをクリックすると、対応するコンテンツまでスムーズにスクロールします。 長いページの目次や機能紹介などにも利用できます。
サンプルやコード例など、実際の内容を紹介するコンテンツを配置できます。 スクロールすると対応する「サンプル」タブが自動で選択されます。
カスタマイズ方法や応用例などを掲載できます。 コンテンツが長いページでも現在表示している位置をタブから確認できます。
最後のコンテンツまでスクロールすると、「まとめ」タブが自動で選択されます。 タブをクリックして前のコンテンツへ戻ることもできます。
ページをスクロールすると現在位置に対応するタブが自動で切り替わり、タブをクリックすると対応するコンテンツへ移動します。
コードをコピーして使おう!
<!DOCTYPE html>
<html lang="ja">
<head>
<!-- 文字コード -->
<meta charset="UTF-8">
<!-- スマートフォン対応 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ページタイトル -->
<title>スクロールに連動して切り替わるタブ</title>
<!-- CSSファイル -->
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- スクロール連動タブ全体 -->
<div class="scroll-linked-tabs_wrap">
<!-- タイトル -->
<div class="scroll-linked-tabs_title">
スクロールに連動するタブ
</div>
<!-- 説明文 -->
<p class="scroll-linked-tabs_text">
スクロールすると、表示位置に合わせて対応するタブが自動で切り替わります。
</p>
<!-- タブ一覧 -->
<div class="scroll-linked-tabs_tabs" aria-label="コンテンツ一覧">
<!-- 概要タブ -->
<button
class="scroll-linked-tabs_tab is-active"
type="button"
data-target="scroll-linked-tabs-overview">
概要
</button>
<!-- 特徴タブ -->
<button
class="scroll-linked-tabs_tab"
type="button"
data-target="scroll-linked-tabs-feature">
特徴
</button>
<!-- 使い方タブ -->
<button
class="scroll-linked-tabs_tab"
type="button"
data-target="scroll-linked-tabs-usage">
使い方
</button>
<!-- サンプルタブ -->
<button
class="scroll-linked-tabs_tab"
type="button"
data-target="scroll-linked-tabs-sample">
サンプル
</button>
<!-- 応用タブ -->
<button
class="scroll-linked-tabs_tab"
type="button"
data-target="scroll-linked-tabs-custom">
応用
</button>
<!-- まとめタブ -->
<button
class="scroll-linked-tabs_tab"
type="button"
data-target="scroll-linked-tabs-summary">
まとめ
</button>
</div>
<!-- 概要コンテンツ -->
<div
class="scroll-linked-tabs_panel"
id="scroll-linked-tabs-overview">
<div class="scroll-linked-tabs_panel-title">
概要
</div>
<p class="scroll-linked-tabs_panel-text">
スクロール位置を検知し、現在表示しているコンテンツに対応するタブを自動で強調表示します。
ページを下へスクロールして、タブの表示が変化することを確認できます。
</p>
</div>
<!-- 特徴コンテンツ -->
<div
class="scroll-linked-tabs_panel"
id="scroll-linked-tabs-feature">
<div class="scroll-linked-tabs_panel-title">
特徴
</div>
<p class="scroll-linked-tabs_panel-text">
タブ部分は画面上部に固定されるため、コンテンツをスクロールしても現在位置を確認できます。
表示するセクションが変わると、対応するタブも自動で切り替わります。
</p>
</div>
<!-- 使い方コンテンツ -->
<div
class="scroll-linked-tabs_panel"
id="scroll-linked-tabs-usage">
<div class="scroll-linked-tabs_panel-title">
使い方
</div>
<p class="scroll-linked-tabs_panel-text">
タブをクリックすると、対応するコンテンツまでスムーズにスクロールします。
長いページの目次や機能紹介などにも利用できます。
</p>
</div>
<!-- サンプルコンテンツ -->
<div
class="scroll-linked-tabs_panel"
id="scroll-linked-tabs-sample">
<div class="scroll-linked-tabs_panel-title">
サンプル
</div>
<p class="scroll-linked-tabs_panel-text">
サンプルやコード例など、実際の内容を紹介するコンテンツを配置できます。
スクロールすると対応する「サンプル」タブが自動で選択されます。
</p>
</div>
<!-- 応用コンテンツ -->
<div
class="scroll-linked-tabs_panel"
id="scroll-linked-tabs-custom">
<div class="scroll-linked-tabs_panel-title">
応用
</div>
<p class="scroll-linked-tabs_panel-text">
カスタマイズ方法や応用例などを掲載できます。
コンテンツが長いページでも現在表示している位置をタブから確認できます。
</p>
</div>
<!-- まとめコンテンツ -->
<div
class="scroll-linked-tabs_panel"
id="scroll-linked-tabs-summary">
<div class="scroll-linked-tabs_panel-title">
まとめ
</div>
<p class="scroll-linked-tabs_panel-text">
最後のコンテンツまでスクロールすると、「まとめ」タブが自動で選択されます。
タブをクリックして前のコンテンツへ戻ることもできます。
</p>
</div>
</div>
<!-- JavaScriptファイル -->
<script src="script.js"></script>
</body>
</html>
サンプル一式を取得する場合 HTML・CSSなどすべてのファイルが必要な場合は、「サンプル一式をダウンロード」をクリックしてください。
ファイル構成と設置方法
このサンプルはHTML・CSS・JavaScriptの3ファイルで構成されています。HTMLでは6つのタブと、それぞれに対応する「概要」「特徴」「使い方」「サンプル」「応用」「まとめ」のコンテンツを作成します。CSSではタブのデザインや画面上部への固定、各コンテンツの表示、スマートフォン向けのレイアウトを設定します。JavaScriptではスクロール位置を監視し、現在表示しているコンテンツに対応するタブを自動でアクティブにします。
sample/
├── index.html
├── style.css
└── script.js
各ファイルの役割
index.htmlはスクロール連動タブ全体を構成するファイルです。6つのタブと、それぞれのタブに対応するコンテンツを記述しています。各タブのdata-targetと各コンテンツのidを対応させることで、クリックしたタブから移動するコンテンツと、スクロール時に強調表示するタブを関連付けています。
style.cssはタブとコンテンツのデザインを設定するファイルです。全体の横幅や余白、背景色、枠線、角丸、タブのサイズ、アクティブ時の色などを設定しています。position:sticky;によってタブ一覧をスクロール中も画面内へ固定し、scroll-margin-topによってタブをクリックしたときのコンテンツの停止位置を調整しています。
script.jsはタブのクリックとスクロール位置に応じた切り替えを行うファイルです。タブをクリックするとscrollIntoView()で対応するコンテンツまでスムーズにスクロールします。また、Intersection Observerで各コンテンツを監視し、判定位置に入ったコンテンツと対応するタブへis-activeクラスを付けます。
設置方法・使い方
sampleフォルダへindex.html、style.css、script.jsを配置します。3つのファイルを同じ階層へ保存したあと、sample/index.htmlをブラウザで開いてください。index.htmlからstyle.cssとscript.jsを読み込む構成になっているため、追加のライブラリや外部サービスを用意する必要はありません。
ページを下へスクロールすると、現在の判定位置に入ったコンテンツに対応して「概要」「特徴」「使い方」「サンプル」「応用」「まとめ」のタブが順番に強調表示されます。タブ一覧はスクロール中も画面内へ固定されます。また、任意のタブをクリックすると、そのタブに対応するコンテンツまでスムーズにスクロールできます。
カスタマイズできる内容
index.htmlでは、全体のタイトルや説明文、6つのタブ名、各コンテンツのタイトルと本文を変更できます。タブとコンテンツの対応関係を変更する場合は、タブのdata-targetと移動先コンテンツのidを同じ値に合わせてください。
style.cssでは、全体の最大横幅や余白、背景色、枠線、角丸、タブの高さ、文字サイズ、通常時とアクティブ時の色、コンテンツの高さなどを変更できます。タブの固定位置やクリック後のスクロール停止位置も数値から調整できます。script.jsではIntersection ObserverのrootMarginを変更することで、スクロール中にタブを切り替える判定位置を調整できます。
数値調整
style.css
max-width:700px;
タブ全体の最大横幅です。値を大きくすると全体が横に広がり、小さくするとコンパクトになります。
margin:40px auto;
タブ全体の上下余白です。40pxを大きくすると上下の間隔が広がり、小さくすると狭くなります。
padding:32px;
タブ全体の内側余白です。値を大きくすると内容と外側の枠線との間隔が広がり、小さくすると狭くなります。
border-radius:18px;
タブ全体を囲む枠の角丸です。値を大きくすると丸みが強くなり、0にすると四角になります。
font-size:22px;
全体タイトルの文字サイズです。値を大きくするとタイトルが大きくなり、小さくすると控えめになります。
top:10px;
PC表示でタブ一覧を固定する位置です。画面上端から10pxの位置で固定され、値を大きくすると固定位置が下がります。
padding-top:8px;
固定されるタブ一覧の上側余白です。値を大きくするとタブ上部の余白が広がります。
min-height:52px;
PC表示でのタブの最小高さです。値を大きくするとタブが高くなります。
padding:14px 8px;
PC表示でのタブの内側余白です。14pxは上下、8pxは左右の余白を表します。値を大きくするとタブ内部の余白が広がります。
border-radius:12px 12px 0 0;
PC表示でのタブ上部の角丸です。12pxを大きくすると上側の丸みが強くなります。
font-size:14px;
PC表示でのタブの文字サイズです。値を大きくすると文字が大きくなります。
margin-left:4px;
PC表示で隣り合うタブ同士の間隔です。値を大きくするとタブの間隔が広がります。
.3s
タブの背景色と文字色が変化する時間です。0.3秒で切り替わり、値を大きくするとゆっくり、小さくすると速く変化します。
min-height:320px;
PC表示での各コンテンツの最小高さです。値を大きくすると1つのコンテンツが占める縦方向の範囲が広がり、スクロールする距離も長くなります。
padding:24px;
各コンテンツの内側余白です。値を大きくすると本文と枠線との間隔が広がります。
scroll-margin-top:80px;
PC表示でタブをクリックしてコンテンツへ移動するときの上側の余白です。値を大きくすると、スクロール後にコンテンツが画面上端から離れた位置で停止します。
margin-top:24px;
2個目以降のコンテンツに設定する上側の余白です。値を大きくするとコンテンツ同士の間隔が広がります。
font-size:20px;
各コンテンツタイトルの文字サイズです。値を大きくするとタイトルが大きくなります。
script.js
rootMargin:"-30% 0px -60% 0px"
Intersection Observerがコンテンツを検知する範囲を調整する値です。上側30%と下側60%を監視範囲から除き、残った画面内の範囲へコンテンツが入ったときに対応するタブをアクティブにします。上下の割合を変更すると、スクロール中にタブが切り替わる判定位置を変更できます。
threshold:0
コンテンツが判定領域へ入った時点で検知する設定です。0では監視対象が判定領域へ入り始めたタイミングでIntersection Observerの条件を満たします。
レスポンシブ対応
このサンプルはレスポンシブ対応です。style.cssのwidth:100%とmax-width:700pxによって、画面幅に合わせて全体の横幅が縮小されます。画面幅640px以下ではpadding:24px 18px;へ変更し、全体の左右余白を小さくします。
640px以下ではタブ一覧へflex-wrap:wrap;を設定し、各タブをcalc(33.333% - 4px)を基準とした幅にすることで、6つのタブを3列2段に配置します。タブの最小高さは44px、文字サイズは13pxへ変更し、スマートフォンでも操作しやすい大きさに調整しています。
各コンテンツも640px以下ではmin-height:280px、padding:20px 16pxへ変更します。固定タブが2段になることを考慮してscroll-margin-top:120pxへ変更しているため、スマートフォン・タブレット・PCの画面幅に合わせて利用できます。
コメント