🚀

CSS GridでヘッダーだけをStickyにする方法

2023/08/28に公開

メモです。

  • header
  • main
  • footer

の3行構成のページで、main の内容が少ないときでも footer が画面の最下部に来るようにしたい場合、CSS Gridを使って以下のように書くことができます。

<div id="grid">
  <header>header</header>
  <main>main</main>
  <footer>footer</footer>
</div>
#grid {
  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: 100vh;
}

この状態からさらにheader だけを position: sticky; 相当にしたい場合は、以下のようにすればよいというお話です。

<div id="grid">
  <header>header</header>
  <div id="wrapeer">
    <main>main</main>
    <footer>footer</footer>
  </div>
</div>
#grid {
  display: grid;
  grid-template-rows: auto 1fr;
  height: 100vh;
}

#wrapper {
  display: grid;
  grid-template-rows: 1fr auto;
  overflow: auto;
}

動作例はこちら。

追記

Next.js 制のアプリでこの実装を使ったところ、next.config.jsexperimental: { scrollRestoration: true } を設定しているにもかかわらずブラウザバックでスクロール位置が復元しない挙動になってしまいました。

調べたところ、History APIの scrollRestoration が、ページ全体のスクロール位置の復元しかできない(今回のような実装で main の中身だけが hidden: scroll によってスクロールされたその位置までは復元できない)仕様のようです。

参考:History API でもページバック時にスクロールバーの位置は復元される #復元できないケース

というわけで、もしこれが問題になる場合は、CSS Gridを使うのは諦めるしかなくて、例えば以下のような実装で代替できるかと思います。

<div id="wrapper">
  <header>header</header>
  <main>
    <div>
      <button id="short">short content</button>
      <button id="long">long content</button>
    </div>
    <div id="content">short content</div>
    <br><br>
  </main>
  <footer>footer</footer>
</div>
#wrapper {
  min-height: 100vh;
}

header {
  position: sticky;
  top: 0;
}

footer {
  position: sticky;
  top: 100vh;
}

動作例はこちら。

参考:この実装方法は巧い! コンテンツが少ない量でもフッタを一番下に配置するCSSのテクニック | コリス

GitHubで編集を提案

Discussion