できない.dev

CSSでヘッダーを上部に固定するには

position: sticky でスクロール領域の先頭にヘッダーを貼り付ける基本形を示す。
スクロールしても見出しが消えないため、長い一覧でも今どこを見ているかが分かる。

公開: 更新:

プレビュー
<div class="scroll-area">
  <div class="sticky-header">固定ヘッダー</div>
  <p>行 1</p>
  <p>行 2</p>
  <p>行 3</p>
  <p>行 4</p>
  <p>行 5</p>
  <p>行 6</p>
</div>
.scroll-area {
  height: 160px;
  overflow-y: auto;
  border: 1px solid #e2e8f0;
  border-radius: 8px;
  background: #fff;
}
.sticky-header {
  position: sticky;
  top: 0;
  padding: 10px 14px;
  background: #0f766e;
  color: #fff;
  font-weight: 700;
}
.scroll-area p {
  margin: 0;
  padding: 12px 14px;
  border-bottom: 1px solid #f1f5f9;
}

position: sticky は通常のフローに置かれたまま、指定した top の位置まで来ると貼り付く。

top を省くと貼り付く位置が決まらず、静的配置と同じ見た目になる。
そのため sticky には必ず top(または left / right / bottom)を添える。

つまずき

sticky が効かないときに多い原因は 2 つある。

  • 祖先要素に overflow: hidden / auto / scroll が付いている(最も多い)
  • スクロールする側の高さが中身と同じで、そもそも貼り付く余地が無い

sticky 要素は最も近いスクロール可能な祖先を基準に貼り付く。
途中に別のスクロールコンテナがあると、そちらの中で貼り付いてしまい、期待した位置に留まらない。

上の例では .scroll-area に height と overflow-y を与えることで、この 2 点を満たしている。

position: fixed との違い

fixed はビューポート基準で完全に浮くため、後続のコンテンツがその下へ潜り込む。
レイアウト側で余白を確保する必要がある。

sticky は元の場所を占有したまま貼り付くので、重なりや詰まりが起きにくい。
使い分けの基本は次のとおりである。

  • ページ全体のグローバルヘッダー → fixed
  • 一覧やテーブルの見出し行 → sticky
できない例: fixed で余白を取らない(行 1 が潜る)
.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  padding: 10px 14px;
  background: #0f766e;
  color: #fff;
  font-weight: 700;
}
p {
  margin: 0;
  padding: 10px 14px;
  border-bottom: 1px solid #e2e8f0;
}
できる例: sticky は元の場所を占める
.header {
  position: sticky;
  top: 0;
  padding: 10px 14px;
  background: #0f766e;
  color: #fff;
  font-weight: 700;
}
p {
  margin: 0;
  padding: 10px 14px;
  border-bottom: 1px solid #e2e8f0;
}