📝

【CSS Sticky & Flex】個人的によくやっている固定ヘッダー・フッターの方法

2021/10/14に公開

画面上部の追従ヘッダーと、コンテンツの高さがウィンドウ高さより短くても常にウィンドウ下部にあるフッターというレイアウトはよくあるでしょう。そんなレイアウトを実装するCSSを紹介します。細かいCSSの解説などは割愛しています。なおはIE11は非対応なので、その点はご留意ください。

実装例

コード

レイアウトに関しては以下のようなHTMLとCSSで実装されています。

<div class="wrapper">
  <header>ヘッダー</header>
  <main>
    <!-- 省略 -->
  </main>
  <footer>フッター</footer>
</div>
.wrapper {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

header {
  position: sticky;
  top: 0;
  width: 100%;
}

main {
  flex-grow: 1;
}

上記のようなCSSを適用することで、コンテンツ部分の高さが可変でもフッターは常に画面下部にあり、ヘッダーがついてくるレイアウトになります。

フッターが常に下部になる仕組み

.wrapperがウィンドウ高さ(100vh)を最低限の高さとして確保しつつFlexboxレイアウトを展開します。.wrapper内部は<header>部分、<main>部分、<footer>部分の3つに分割され縦に並んでいます。注目したいのが<main>部分にflex-grow: 1という指定になっています。これはFlexboxレイアウトの余った部分に関するプロパティで、余った分は<main>がそれを埋める、という挙動になります。

これにより、<main>内部のコンテンツ高さが短くても残余分の高さが常に確保されているので、フッターが上がってくることなく、常にウィンドウ下部にいます。.wrapperの高さ指定はあくまでmin-heightなので、コンテンツが十分にあれば自動的に伸びます。

ヘッダーがついてくる仕組み

上部固定ヘッダーなのでposition: fixedで良いと思うかもしれませんが、わざわざposition: stickyを使うのには訳があります。position:fixedにすると<header>の高さ分だけレイアウト計算に含まれなくなるので、その分<main>部分が上がってきてしまいます。それを相殺するため<main>margin-top(あるいはpadding-top)にヘッダーの高さ分だけの固定値を設定する必要があります。<header>の高さが変更になった場合、<main>margin-topも箇所を変更しなくてはなりません。

position: stickyはスティッキー挙動になる前は通常の要素のような(position: staticな) 挙動になります。そのため、<header>の高さはレイアウト計算に含まれるようになり、<main>margin-topなど指定せずとも<header>の下におさまります。もちろん、<header>の高さが変わっても自動的に位置が変わります。

同時に<header>にはtop: 0が指定されているので、初めからスティッキー挙動(ウィンドウ上部にくっつく)になります。position: stickyを使うとposition: fixedっぽい挙動とレイアウトの面倒さを解決できます。

IE11での見え方

ちなみにIE11では非対応ですが、固定される機能がなくなるだけで大きな崩れはありません。グレースフルデグラデーションな考え方が採用されるのならば、固定機能は提供されませんがコンテンツとしては閲覧可能なので許容範囲内ではないでしょうか。

まとめ

固定ヘッダーとフッターはFlexboxとStickyを組み合わせると複雑な処理などもせず数行のCSSで実装できます。適用するのがグローバルなレイアウトを組む部分とその子要素だけで済むので影響範囲も少なくオススメです。

Discussion