この記事では、CSSのposition: sticky;を使い、サイドバーの要素をスクロール途中から一定の位置へ固定する方法を解説します。当サイトのように、トップページでは人気記事、記事詳細ページでは目次を追従させる使い分けも含め、基本のHTMLとCSS、効かないときの確認点まで初心者向けに整理します。
読者トップページでは人気記事、記事詳細ページでは目次がスクロールに付いてきますが、同じ仕組みですか?
木村はい、どちらもCSSのposition: sticky;を使っています。ページの種類に合わせて固定する要素を切り替えています。
読者position: fixed;と同じようなものですか?
木村少し違います。fixedは画面を基準に固定しますが、stickyは親要素の範囲内だけで固定されるため、サイドバーに使いやすいです。
読者コードは短そうですが、効かないこともあると聞いて不安です。
木村基本コードに加えて、top、親要素のoverflow、FlexboxやGridの伸び方を確認すれば解決しやすくなります。順番に見ていきましょう。
position: stickyとは?
position: sticky;は、要素を最初から固定するのではなく、スクロールによって指定位置へ到達したときだけ固定するCSSです。長い記事のサイドバー、目次、カテゴリー案内などに向いています。
親要素の範囲内で追従する
stickyを指定した要素は、通常のレイアウト位置を保ちながらスクロールします。topで指定した位置へ到達すると固定され、親要素の下端まで来ると追従を終えます。
ページ全体に重なり続けにくいため、メインコンテンツとサイドバーを並べるレイアウトで扱いやすいのが特徴です。
fixedとの違い
position: fixed;は画面を基準に要素を固定し、元のレイアウト位置から外れます。一方、stickyは元の場所を保ち、親要素の範囲内だけで動きます。
- sticky:記事の目次やサイドバーなど、範囲を限定して追従させたいとき
- fixed:画面右下のボタンなど、常に同じ画面位置へ表示したいとき
サイドバーを追従固定する実装方法
実装の基本は、メインコンテンツとサイドバーを横並びにし、固定したいサイドバー内の要素へposition: sticky;とtopを指定することです。
HTMLでメインコンテンツとサイドバーを用意する
次のHTMLでは、mainとasideを同じ親要素の中へ配置しています。実際の本文や人気記事の内容は、サイトに合わせて置き換えてください。
<div class="layout">
<main class="main-content">
<h2>記事タイトル</h2>
<p>ここに長い記事本文が入ります。</p>
</main>
<aside class="sidebar">
<section class="sidebar__sticky">
<h2>人気記事</h2>
<ol>
<li><a href="#">記事タイトル</a></li>
</ol>
</section>
</aside>
</div>この段階では固定されません。次に、横並びと追従位置をCSSで設定します。
CSSで横並びとstickyを指定する
.layoutをGridで2列にし、.sidebar__stickyへstickyを指定します。align-items: start;は、子要素が縦方向へ不要に引き伸ばされるのを防ぐための指定です。
.layout {
display: grid;
grid-template-columns: minmax(0, 1fr) 320px;
gap: 32px;
align-items: start;
}
.sidebar__sticky {
position: sticky;
top: 24px;
}実行後は、人気記事が画面上端から24pxの位置に到達したときに固定され、親要素の終端まで追従します。JavaScriptは必要ありません。
固定ヘッダーがある場合はtopを調整する
上部に固定ヘッダーがあるサイトでtop: 0;にすると、サイドバーがヘッダーの裏へ隠れることがあります。ヘッダーの高さと余白を足した値を指定します。
:root {
--header-height: 80px;
}
.sidebar__sticky {
position: sticky;
top: calc(var(--header-height) + 24px);
}ヘッダーの高さをCSS変数で管理しておくと、デザイン変更時も調整しやすくなります。
当サイトでの人気記事と目次の使い分け
当サイトでは、トップページでは人気記事、記事詳細ページでは目次を一定位置へ固定しています。表示する内容と追従させるCSSを分けて考えると、WordPressでも仕組みを整理しやすくなります。
トップページでは人気記事を固定する
トップページの人気記事は「WordPress Popular Posts」で集計し、テーマのsidebar.phpで一覧を出力しています。人気記事を取得する処理と、一定位置へ固定するCSSは別の機能です。
トップページでは、人気記事のセクションへsidebar__section--stickyクラスを追加して追従させています。WordPress標準機能に固定表示を設定する管理画面はないため、テーマまたは子テーマのCSSでstickyを指定します。プラグイン本体を直接編集する必要はありません。
記事詳細ページでは目次を固定する
記事詳細ページでは、人気記事ではなく、その下に表示する記事内目次を固定します。読者が長い記事を読み進めながら各見出しへ移動できるよう、article-tocへstickyを指定しています。
@media (min-width: 981px) {
.sidebar__section--sticky {
position: sticky;
top: 108px;
}
}
.article-toc {
position: sticky;
top: 108px;
max-height: calc(100vh - 128px);
overflow: hidden;
}トップページではsidebar__section--sticky、記事詳細ページではarticle-tocが追従します。どちらもtop: 108px;で固定ヘッダーと余白を避けていますが、この数値はサイトのヘッダー高に合わせて変更してください。
スマホでは固定を解除する
スマホでは画面幅が狭く、サイドバーが本文の下へ移動することが一般的です。当サイトでは980px以下で人気記事のstickyを有効にせず、記事詳細ページの追従目次も非表示にしています。
固定する要素が画面より高いと内容を読み切れない場合があります。狭い画面では固定を解除するか、必要に応じて要素内のスクロールを設計してください。
position: stickyが効かない原因
stickyの指定自体は短いものの、周囲のレイアウトの影響を受けます。効かないときは、次の項目を上から順番に確認すると原因を見つけやすくなります。
topが指定されていない
position: sticky;だけでは、どの位置で固定するか決まりません。通常はtopも一緒に指定します。まずはtop: 0;またはtop: 24px;で動作を確認してください。
祖先要素のoverflowが影響している
親要素やさらに外側の要素にoverflow: hidden;、auto、scrollなどが指定されていると、その要素がスクロールの基準になる場合があります。装飾目的で付けたoverflowも含めて確認しましょう。
必要のない指定なら削除し、必要な指定なら「どの要素の中で追従させたいか」に合わせてHTML構造を見直します。
FlexboxやGridで要素が引き伸ばされている
FlexboxやGridの初期設定によって、サイドバーがメインコンテンツと同じ高さまで伸びることがあります。親要素へalign-items: start;、またはsticky要素へalign-self: start;を指定して確認します。
親要素が短い・固定要素が高すぎる
stickyは親要素の範囲内で動くため、親要素に十分な高さがなければ追従する距離がありません。また、固定する要素が画面より高いと、固定中に下部が見えにくくなります。
動作確認のために無理な固定高さを付けるのではなく、実際の本文量、サイドバーの内容量、画面の高さを見ながら調整することが大切です。
まとめ
position: sticky;は、サイドバーや人気記事を読みやすい位置へ追従させる、シンプルで便利なCSSです。position: sticky;とtopをセットで指定する- stickyは親要素の範囲内で固定される
- 固定ヘッダーがある場合は
topへ高さと余白を含める - 効かないときは
overflow、Flexbox・Grid、親要素の高さを確認する - スマホでは固定を解除すると読みやすくなることが多い
- まずは固定したい要素へクラスを付け、PC表示で
top: 24px;から試してみてください。ページの役割に合わせて対象を切り替えると、当サイトのようにトップページでは人気記事、記事詳細ページでは目次を追従できます。

stickyが効かない原因としてoverflow指定も関係することを初めて知りました。親要素を順番に確認する方法で原因を見つけられました。ありがとうございます。
ありがとうございます。stickyは対象要素だけでなく、祖先要素のoverflowや高さの影響も受けます。近い親要素から順番に確認すると原因を切り分けやすいです。