スクロールしても常に表示されるヘッダーやフッターを作成したい場合、まっさきに思いつくのは position: fixed; を使った実装です。

position: fixed; を指定した要素は他の要素から浮き上がります。その結果、fixed を指定していない他の要素が fixed された要素の裏側に重なるようになります。

このとき、例えば重なった部分の下の要素に文字が書いてあるとそれは隠れてしまうので、fixed 要素の高さの分だけ padding を足したり… といったことが必要になります。

fixed している要素の高さが内容に応じて変わったりする場合、padding の高さを固定値にはできないので、動的に取得するのかうんぬん… となり、なかなかに面倒くさいです。

これらの問題はそもそも fixed を使用しないことで解決できます。

display: flex; で実装するヘッダー/フッター

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  </head>
  <body>
    <header>I am Header</header>
    <main>
      <div>I am Start in Main</div>
      <div>I am Body in Main</div>
      {... 他にもたくさんの要素があるとして}
      <div>I am Body in Main</div>
      <div>I am End in Main</div>
    </main>
    <footer>I am Footer</footer>
  </body>
</html>

<style>
  html {
    height: 100%; /* required */
  }
  body {
    margin: 0px;
    display: flex; /* required */
    flex-direction: column; /* required */
    height: 100%; /* required */
  }
  header {
    height: 80px;
    background-color: cyan;
  }
  main {
    flex-grow: 1; /* required */
    overflow-y: auto; /* required */
    background-color: magenta;
  }
  footer {
    height: 80px;
    background-color: yellow;
  }
</style>

上記でいえば <header> 要素と <footer> 要素がヘッダーとフッターになっていて、それぞれ画面の上部と下部に常に表示されます。

<main> 要素がヘッダーとフッターに挟まれたスクロール可能なエリアです。

漠っとだけ説明すると、<header><footer><main> の親要素(ここでは <body>)で display: flex; および flex-direction: column; し、<main> 要素に flex-grow: 1;overflow-y: auto; するのがポイントです。このとき親要素(<body>)に高さを持たせるのを忘れないようにしてください(ここでは height: 100%; としています)。

実装に必要な記述には /* required */ のコメントをつけておきました。それ以外の css は単に色をつけたりと分かりやすくするためだけのものなので記載しなくて問題ありません。