HTML / CSS約8分

stickyが止まる範囲を調べる:親の高さとoverflowを見る

追従見出しが動かなかったり、途中で画面から消えたりするときに。架空の工房案内でstickyが止まる範囲を調べ、上端の指定、親の高さ、祖先のoverflowを一つずつ確認する手順を紹介します。

この記事の目次
  1. 「上端で止まる」と「節から出ない」を同時に考える
  2. 枠線のある節で、追従の始まりと終わりを見る
  3. 追従しない場合は、topと親の長さを一つずつ変える
  4. 親が十分長くても動かないなら、祖先のoverflowを見る
  5. 追従をやめる条件も、表示の目的から決める
  6. 追従前・追従中・節の終わりを見比べる

position: stickyを付けたのに見出しが追従しない。あるいは途中まで追従して、節の終わりで消える。どちらも見た目だけでは「効いていない」と感じますが、調べる場所は同じとは限りません。stickyが止まる範囲を調べるには、止まる位置と、移動できる範囲を分けて観察します。

この記事では、HTMLの親子関係とCSSのクラス指定が分かる人向けに、架空の染色工房の見学案内を作ります。見学の節を読む間だけ見出しを残し、次の節へ進んだら退場させる構成です。既存サイトを触る前に、単独の練習ファイルで動きを比較してください。

「上端で止まる」と「節から出ない」を同時に考える

stickyは、通常の文章の並びに場所を持ちながら、スクロールに応じて表示位置を調整する指定です。縦方向の追従では、たとえばtop: 1remを使って、スクロール領域の上端からどれだけ離して止めるかを決めます。

ただし、ページの最後まで自由に付いてくる指定ではありません。位置を制約する箱を「包含ブロック」と呼び、この例では見出しを直接含むsectionがその役割を持ちます。sectionの下端に達すると、見出しも節と一緒に上へ流れていきます。

MDNのpositionの説明では、stickyが参照するスクロール祖先と、topなどの指定を確認できます。W3Cの配置仕様草案は、追従する際も包含ブロックに収まる制約を説明しています。以下の例では「上端の目安」と「sectionの下端」を別々に見ると、その制約を追えます。

枠線のある節で、追従の始まりと終わりを見る

新しいHTMLファイルのbody内に次の断片を置きます。headには文字コードとviewportを設定し、続くCSSをstyle要素または同じページで読み込むCSSファイルへ入れてください。見出しを囲む余分な箱は付けません。

<header class="intro">
  <h1>染色工房の見学(架空の練習例)</h1>
  <p>下へスクロールして見学の流れを確認します。</p>
</header>
<main>
  <section class="tour">
    <h2 class="tour-heading">見学の流れ</h2>
    <div class="tour-body">
      <p>入口で受付を行います。</p>
      <p>道具の説明を聞いてから、作業台へ進みます。</p>
      <p>見学後は入口へ戻ります。</p>
    </div>
  </section>
  <section class="after">
    <h2>見学後の案内</h2>
    <p>ここでは前の見出しの追従が終わります。</p>
  </section>
</main>
* { box-sizing: border-box; }
body {
  margin: 0;
  padding: 1rem;
  font-family: sans-serif;
  line-height: 1.7;
}
main { max-width: 48rem; margin-inline: auto; }
.intro { min-height: 70vh; }
.after { min-height: 110vh; }
.tour { border: 2px solid #333; }
.tour-heading {
  position: sticky;
  top: 1rem;
  margin: 0;
  padding: 0.75rem;
  background: #ffe0c6;
}
.tour-body { min-height: 140vh; padding: 1rem; }
@media (max-width: 40rem) {
  .tour-heading { position: static; }
}

幅を広くして開き、見出しが画面上部へ近付くまでスクロールします。最初は節と一緒に動き、上から1remの位置に来ると留まり、最後は節の下端と一緒に上へ消えるはずです。下端が近いところで上へスクロールを戻し、同じ範囲で留まることも比べます。

vhは画面の高さを基準にした単位です。大きなmin-heightは短い原稿でも追従を観察する距離を作るために入れています。本番の本文にこの空白を足す提案ではありません。背景色は、後ろの文章と見出しが重なる際に文字が混ざらないように付けています。

追従しない場合は、topと親の長さを一つずつ変える

まずtop: 1remだけを外して試します。この例では縦方向の停止位置が指定されなくなり、見出しはそのまま上へ流れます。positionがstickyになっているだけで完成とせず、topを戻して上端に留まることを再確認してください。

次に、h2だけを新しいdivで囲み、そのdivの後ろにtour-bodyを置いてみます。余白も高さもないその箱は見出しとほぼ同じ高さなので、箱の中を追従できる距離がなくなります。見出しがすぐ消える原因は、ページ全体の文章量ではなく、移動を制約する箱の短さです。

この失敗はtopを0にしても解決しません。今回の修正は追加したdivを外し、h2を長いtourの直接の子へ戻すことです。実際の制作では、見出しと追従させたい本文を同じ範囲へ入れるなど、意味に合う構造を選びます。直した後は、枠線の下端で追従が終わるかを再確認しましょう。

CSSの値が上書きされている場合は、適用元を調べる記事の手順で計算済みのpositionとtopを確認できます。値が合っているのに動かない段階で、親の範囲へ調査を進めます。

親が十分長くても動かないなら、祖先のoverflowを見る

元の構造へ戻し、今度はtourにoverflow: hiddenを追加します。ページをスクロールしても、先ほどのように画面上端へ留まらなくなる条件を作れます。hiddenを「はみ出しを隠すだけ」と考えると、この変化を見落とします。

stickyはoverflowがhidden、auto、scrollなどでスクロールの仕組みを作る最寄りの祖先を参照します。その箱が実際に画面上でスクロールしているとは限りません。この例のtourには高さ制限がなく、内容に合わせて伸びるため、ページを動かしてもtour内のスクロール位置は変わりません。

修正では追加したoverflowを取り除き、元の追従が戻るか確かめます。既存サイトでは、祖先の指定を無条件に削除しないでください。内部をスクロールさせる必要がある箱なら、その箱の中で追従する設計が合う場合もあります。「どの領域を動かしたとき残したいか」を先に決め、祖先を一つずつたどります。

追従をやめる条件も、表示の目的から決める

提示例は40rem以下で通常配置へ戻します。狭い画面で見出しが何行にもなり、本文を読む領域を占めるなら、常に残す利点より読みづらさが大きくなるためです。この数値は練習用の境界であり、すべてのサイトに適する寸法ではありません。

広い画面でも文字を拡大し、見出しが画面の大部分を覆うなら追従の解除や内容の短縮を検討します。本文が短く、すぐ次の節に入る場合も、追従なしで十分です。反対に、長い説明の途中で現在の節名を確認したい場面には、この構成を使えます。

「止まらないからfixedへ替える」という修正は、今回の完成条件に合いません。節の終わりで退場する理由を保ったまま直す必要があります。固定ヘッダーへのページ内リンクが隠れる問題は、移動先の余白を調整する記事で扱う別の確認です。

追従前・追従中・節の終わりを見比べる

元のコードで、幅1280pxと幅390pxを順に試します。広い画面では、追従前・追従中・節の終了時の三枚を記録し、次の条件を照合してください。

  • 節が上へ近付く前は、見出しが節と一緒に動いている。
  • 追従中は、上端に約1remの空きがあり、背景越しに本文が混ざらない。
  • 節の下端を越えると、前の見出しが次の節へ居残らない。
  • 幅390pxでは通常配置になり、見出しと本文を順に読める。

最後にtopの削除だけを再現し、戻したとき二つ目の条件を満たすことを確認します。幅ごとの確認を続けるには、レスポンシブCSSの無料レッスンも参照できます。記録には「追従した」だけでなく、どの箱の終わりで止まったかを書き添えましょう。

記事についてのお問い合わせ

記載内容へのご質問や訂正のご連絡は、hello@junkbranding.comまでお願いします。

← 記事一覧に戻る