• position: stickyは常時表示したい部分に使い親の範囲と本文を隠さないようにする

position: stickyは常時表示したい部分に使い親の範囲と本文を隠さないようにする

公開日: 執筆:佐藤

position: stickyは、目次や申込み案内のように、読んでいる間だけ見つけやすくしておきたい部分に使います。画面の端へ常に貼り付けるための指定ではありません。親要素の範囲を出れば元の流れに戻るため、どの区間で見せたいかをHTMLのまとまりで決めます。まず本文を読めること、次に必要な案内へ進めることを守り、そのために固定表示を使います。

Chrome Developersの解説は、Chrome 56でposition: stickyが利用できるようになり、要素が親の範囲と指定した位置の条件でviewportへ留まることを説明しています。指定が書けることと、どの画面でも常時表示してよいことは別です。会社siteで使うなら、固定する部品、親の範囲、狭い画面での扱いを別に決めます。

常時表示と読みやすさを同じ判断にしない

ページを下へ読んでも問い合わせ先や目次を見失わせたくない場面はあります。長いサービス説明の横に問い合わせ案内を置く、用語の多い記事に目次を置く、といった場面です。このとき、案内を見つけやすくする目的と、画面に残し続ける手段を混同しないことが必要です。

小さな画面では、固定した案内が本文の幅や高さを奪います。画面の上端にheaderがあり、その下へさらに目次や申込みbuttonを留めると、読める本文が狭くなります。長い見出し、文字を大きくした表示、横向きのphoneでは、制作時の見本より固定部分が高くなることもあります。案内を常に見せるために本文を隠せば、読者は判断に必要な条件を読めません。

説明用の仮例として、左に本文、右に問い合わせ案内を置くページを考えます。広い画面では、案内を本文の先頭付近から留める設計が候補になります。けれども、phoneでは右側の列が本文の下へ回るため、同じ高さを留める理由は薄れます。狭い画面では通常の文書の流れへ戻し、本文の途中と末尾に問い合わせ先を置く方が、読者にも更新担当者にも分かりやすい場合があります。

position: fixedは、要素を文書の流れから外し、viewportを基準に配置します。一方、position: stickyは通常の流れに置かれた要素が、指定した位置へ達した後に留まる指定です。両方を同じ「固定表示」として扱うと、どこまで表示するのか、親の末尾でどうなるのか、本文との間隔をどこで持つのかが曖昧になります。先に画面へ残す期間を決めます。

親要素は表示を続ける範囲を決める

position: stickyの要素は、親の範囲を越えて残り続けるわけではありません。したがって、ページ全体にある案内を留めたいのか、サービス説明の区間だけにある案内を留めたいのかで、HTMLの親を分けます。見た目だけを見て親を選ぶと、意図しない場所で案内が止まったり、次のsectionへ重なったりします。

次は、本文の横にある案内を、サービス説明のsectionの中だけで留める説明用の例です。

<section class="service-detail">
  <main class="service-body">...</main>
  <aside class="service-contact">...</aside>
</section>
.service-contact {
  position: sticky;
  top: 24px;
}

top: 24pxは、上端から24pxの位置へ達した後に留めるための条件です。この数字を先に決めるより、上に何があるかを確認します。固定しているheaderがあるなら、その高さを避けなければ案内の先頭が隠れます。管理画面からheaderの文言や告知を増やせるsiteでは、短い文だけで試さず、実際に入り得る高さでも見ます。

親要素の高さも重要です。本文が短く、横の案内だけが長い場合、親の終わりに達する前に案内全体を読めないことがあります。反対に、親をページ全体にしてしまうと、サービス説明が終わった後まで案内が残り、別の内容と意味が混ざります。案内が誰に向くものか、どの説明を読んだ後に使うものかを決め、その範囲を親にします。

親や祖先のoverflowも表示へ影響します。既存layoutで高さを整えるためにoverflow: hiddenを使っていると、留めたい要素が期待どおり動かないことがあります。問題が出たときにposition: stickyだけを書き換えるのではなく、親から上へたどり、表示範囲を切る指定、幅、高さ、重なり順を確認します。新しいCSSを足す前に既存の責任を見分ける方が、直す場所を小さくできます。

topの値はheaderの高さと画面の余白から決める

留める位置が画面の上端でよいとは限りません。常に表示するheaderがあるページでは、top: 0にすると案内の見出しやbuttonがheaderの下へ隠れます。headerの高さと、案内を読める余白を合わせて、上端からの距離を決めます。

たとえばheaderが48pxで、案内の上に16pxの余白を残したいなら、topは64pxから試せます。ただし、この値は説明用の仮例です。実際の値はheaderの高さ、browserの表示倍率、管理画面から追加する案内、画面幅で変わります。数字だけをtemplateへ渡すのではなく、何を避けるための余白かを担当者向けの記録へ残します。

固定する案内に問い合わせbuttonを入れるなら、buttonを押した後の画面も確認します。buttonが問い合わせpageへ進むlinkなら、移動先のURLと戻る操作を確かめます。同じページでformを開くbuttonなら、開いたformがheaderや留めた案内に隠れず、keyboardで入力欄へ移動できるかを見ます。表示を留めるCSSと、読者が目的を終える導線は別の作業です。

幅も確認します。横の列が狭くなると、短いbutton文言でも二行になり、留めた案内の高さが増えます。電話番号、受付時間、注意書き、長いlink文言を入れる場合は特に起こりやすいでしょう。狭い幅で横へはみ出す、文字が重なる、buttonの押せる範囲が小さくなる状態は、位置を留めても解決しません。案内の情報を減らすか、本文の流れへ戻すかを先に判断します。

狭い画面では留めない選択を先に用意する

同じCSSを広い画面とphoneへそのまま当てる必要はありません。広い画面で本文と横の案内を並べるためにposition: stickyを使っても、狭い画面では案内を本文の前後へ置き、通常の位置で読ませる設計ができます。留めない状態を失敗と考えず、利用者が条件を読み、必要なら連絡できることを基準にします。

.service-contact {
  position: static;
}

@media (min-width: 1025px) {
  .service-contact {
    position: sticky;
    top: 64px;
  }
}

この例では、最初に通常の文書の流れを用意し、広い画面だけに留める指定を追加しています。対象browserがposition: stickyを解釈しない場合でも、案内そのものは本文の流れで読めます。対応可否を調べることと、案内が消えない形を用意することは、どちらも必要です。

確認は画面幅を変えるだけで終えません。長い本文を最後まで読み、案内が親の終わりで不自然に重ならないかを見ます。headerがあるなら、スクロールした状態で案内の見出しとbuttonが隠れないかを見ます。文字を拡大した状態、長い見出しや電話番号を入れた状態、keyboardでlinkとbuttonへ移動した状態も確かめます。mouseで一度表示が留まっただけでは、問い合わせの入口として使えるかを判断できません。

外部へ制作を頼む場合は、「横の案内をstickyにする」とだけ依頼しません。どのURLのどのsectionで留めるのか、広い画面だけにするのか、上に避けるheaderがあるのか、狭い画面ではどこに置くのかを渡します。完成後には、確認した画面幅とbrowser、通常表示とスクロール後の画面を受け取ります。CSSを任せても、案内の内容と利用者が進む先まで委託先任せにしないためです。

最初の一手は、留めたい案内を一つ選び、それが必要になる本文の区間を決めることです。その区間を親要素にし、広い画面では留めた状態、狭い画面では通常の流れで、本文と問い合わせ先を最後まで確認します。

戻る