【sticky・fixed結局どっち?】HTMLのヘッダーやメニューバーを固定表示させる方法を解説!レスポンシブも
                                  プログラミング学習やWebサイト制作をしている時に、
「HTMLのヘッダーメニューをトップに固定してずっと表示させたい」
「sticky?fixed?結局positionプロパティってどっちを使えば良いの?」
と思ったことはありませんか?
そこで今回は、HTMLのヘッダーやメニューバーを固定表示させる方法について解説します。
この記事を読んでわかる内容は以下の通りです。
- HTMLとCSSだけでヘッダーを固定表示させる方法
 - jQueryを使用してヘッダーの固定表示をカスタマイズする方法
 - positionプロパティのsticky;とfixedの特徴や正しい使い方
 
固定したヘッダーやメニューバーのレスポンシブ対応や、「固定したヘッダーがなぜか重なる…」といったトラブルについての原因と対処法も解説します!
HTMLのヘッダーを固定表示させる方法3つ
HTMLのヘッダーやメニューバーを固定表示させる方法は、以下の3つ。
- HTMLとCSSだけで常時固定表示させる方法
 - jQueryでスクロールの向きに合わせて固定表示させる方法
 - jQueryでページの途中から固定表示させる方法
 
上記3つの方法をマスターしておけば、Webページのデザインや目的などに合わせて使い分けることができます。
では、それぞれの方法について詳しく見ていきましょう。
1.【HTMLとCSSだけ!】最初から最後まで固定表示させる方法
Webページの最初から最後まで、常にヘッダーやメニューバーを固定表示させたい場合は、HTMLとCSSだけで実装することができます。
具体的には、以下のように記述します。
<!-- HTMLコード -->
    <!-- ヘッダー -->
    <header class="header">
      <!-- ヘッダーロゴ -->
      <h1>LOGO</h1>
      <!-- ナビゲーションメニュー -->
      <nav class="nav">
        <ul class="nav_menu">
          <li class="nav_menu_item">メニュー項目1</li>
          <li class="nav_menu_item">メニュー項目2</li>
          <li class="nav_menu_item">メニュー項目3</li>
          <li class="nav_menu_item">メニュー項目4</li>
        </ul>
      </nav>
    </header>
    <!-- TOP画像 -->
    <div class="top">
      <h2>TOP画像</h2>
    </div>
    <!-- コンテンツ -->
    <div class="content">
      <div class="content_item">
        <h2>コンテンツ1</h2>
         <!-- <p>文章は省略<p> -->
          <!-- 以下省略 -->
上記は、HTMLのヘッダーにナビゲーションメニューを設定するコードです。
/* CSSコード */
.header {
  background: #fff;
  display: flex;
  top: 0;
  height: 100px;
  padding: 20px;
  position: fixed;
  justify-content: space-between;
  width: 100%;
}
.top {
  background-color: #3d79bd;
  border: 1px solid #02225233;
  height: 300px;
  text-align: center;
  padding-top: 100px;
}
.top h2 {
  line-height: 200px;
  color: #fff;
}
.nav_menu {
  display: flex;
  padding: 10px;
}
.nav_menu_item {
  margin-left: 20px;
}
.content {
  max-width: 1020px;
  margin: 0 auto;
}
.content_item {
  padding: 30px 0;
}
▼ブラウザ表示▼

CSSでは「position:fixed;」を指定するだけなので、初心者でも簡単に固定表示させることができます。
2.【jQueryを使って】スクロールの向きで固定表示させる方法
スクロールの向きに合わせてヘッダーを固定表示させるには、jQueryを使用します。
先ほど、1で使用したHTMLを例に、CSSとjQueryを記述していきます。
/* CSSコード */
.header.hide {
  top: -100px;
  transition: 0.8s all;
}
上記のコードを、先ほど記述したCSSに追加します。
// jQuery
var _window = $(window),
    _header = $('.header'),
    heroBottom,
    startPos,
    winScrollTop;
 
_window.on('scroll',function(){
    winScrollTop = $(this).scrollTop(); //スクロールトップが
    heroBottom = $('.top').height(); //class="top"の最下部にきたら
    if (winScrollTop >= startPos) {
        if(winScrollTop >= heroBottom){
            _header.addClass('hide'); //class="hide"を付与する=ヘッダーを隠す
        }
    } else {
        _header.removeClass('hide');
    }
    startPos = winScrollTop;
});
 
_window.trigger('scroll');
3.【jQueryを使って】途中から固定表示させる方法
最初からではなく、スクロールの途中でヘッダーを固定表示させる方法を解説します。
<!-- HTMLコード -->
    <!-- TOP画像 -->
    <div class="top">
      <h2>TOP画像</h2>
    </div>
    <!-- ヘッダー -->
    <header class="header">
      <!-- ヘッダーロゴ -->
      <h1>LOGO</h1>
      <!-- ナビゲーションメニュー -->
      <nav class="nav">
        <ul class="nav_menu">
          <li class="nav_menu_item">メニュー項目1</li>
          <li class="nav_menu_item">メニュー項目2</li>
          <li class="nav_menu_item">メニュー項目3</li>
          <li class="nav_menu_item">メニュー項目4</li>
        </ul>
      </nav>
    </header>
    <!-- コンテンツ -->
    以下は1と同様
HTMLは、TOPとヘッダー部分の位置を入れ替えています。
/* CSSコード */
.header {
  background: #fff;
  display: flex;
  padding: 20px;
  position: absolute;
  justify-content: space-between;
  width: 100%;
}
.header.fixed {
  position: fixed;
  top: 0;
  transition: 0.8s all;
}
.top {
  background-color: #3d79bd;
  border: 1px solid #02225233;
  height: 300px;
  text-align: center;
}
.content {
  padding-top: 100px;
  max-width: 1020px;
  margin: 0 auto;
}
CSSは、1と異なる箇所のみ記載しています。
下のコンテンツがヘッダーの高さ分上にカクっとずれてしまわないように、必ずCSSで「position: absolute;」を指定しましょう。
// jQuery
var _window = $(window),
    _header = $('.header'),
    topBottom;
 
_window.on('scroll',function(){     
    topBottom = $('.top').height();
    if(_window.scrollTop() > topBottom){
        _header.addClass('fixed');   
    }
    else{
        _header.removeClass('fixed');   
    }
});
 
_window.trigger('scroll');
スクロールで、TOP画像が見えなくなる時にヘッダーが上部に固定表示される設定になっています。
おまけ:ヘッダーを半透明にしてみよう
ヘッダーを固定表示させると、ヘッダー部分と他のコンテンツ部分が重なっている状態で表示されてしまいます。
ヘッダー部分とコンテンツ部分の違いをわかりやすくするために、ヘッダーを半透明にする方法がよく利用されています。
今回も、1で使用したHTMLを例に、ヘッダーを半透明にするコードを記述します。
/* CSSコード */
.header {
  background: rgb(255, 255, 255, 0.8);
}
上記以外の指定は、1のCSSと同様です。
ヘッダーの背景色を半透明にするには、backgroundプロパティのカラーを「rgb()」で指定し、4つめの数値で透明度を指定します。
position: sticky;とposition: fixed;の違い
どちらも、要素を固定表示させたい場合に利用されるプロパティですが、それぞれ特徴が異なります。
両者の違いをよりわかりやすくするために、まず、同じ要素を固定した際にどのように表示されるのか確認しておきましょう。
【position: sticky;の指定】
/* CSSコード */
.header {
  background: #fff;
  border: 1px solid #333;
  display: flex;
  top: 0;
  height: 100px;
  padding: 20px;
  position: sticky;
  justify-content: space-between;
  width: 100%;
}
.top {
  background-color: #3d79bd;
  border: 1px solid #02225233;
  height: 300px;
  text-align: center;
}
HTMLは、「タイトル名:固定表示させる方法3つ」の1と同様。
CSSは、上記1と異なる箇所を記載しています。
▼ブラウザ表示▼

【display: flex;の指定】
/* CSSコード */
.header {
  background: #fff;
  border: 1px solid #333;
  display: flex;
  top: 0;
  height: 100px;
  padding: 20px;
  position: fixed;
  justify-content: space-between;
  width: 100%;
}
HTMLは、「タイトル名:固定表示させる方法3つ」の1と同様。
CSSは、上記1と異なる箇所を記載しています。
▼ブラウザ表示▼

上記の通り、同じ指定をしても表示が異なります。
「position: fixed;」は、固定したい要素のwidthを指定したり、メインコンテンツに被らないようにmarginで空白を用意しなければならないというのがstickyとの大きな違いです。
なお、stickyは、指定した要素内のコンテナ内でのみ固定されます。
そのため、内包する要素が一つしかない場合はstickyが機能しないので、注意しましょう。
レスポンシブな固定ヘッダーはハンバーガーメニューがおすすめ
メニューバーを固定表示させる際、「文字が多くて見づらい」という問題が発生します。
そこで便利なのが、横三本線のハンバーガーのようなアイコンを使用したメニューバーの「ハンバーガーメニュー」。
スマホなど、レスポンシブ対応のブラウザ上ではアイコンのみ表示されているのが特徴で、アイコンをクリックするとメニューバーが開く仕組みになっています。
通常のメニューバーの場合、ユーザーが間違ってメニューをタップしてしまう可能性もあるため、レスポンシブ対応の固定ヘッダーは、必要な時にのみメニューを表示させることができるハンバーガーメニューがおすすめです。
ハンバーガーメニューの作り方は、以下の記事が参考になります。
HTMLとCSSだけ!】スマホ用ハンバーガーメニューはコピペで実装できる
固定したヘッダーが文字と重なる原因と対処法
「HTMLページの一番上にヘッダーを固定表示させたいのに、なぜか重なる…」
という問題につまづいている方のために、固定ヘッダーと文字(要素)が重なる原因と対処法を解説します。
コード例は、以下の通りです。
<!-- HTMLコード -->
    <!-- ヘッダー -->
    <header class="header">
      <!-- ヘッダーロゴ -->
      <h1>LOGO</h1>
      <!-- ナビゲーションメニュー -->
      <nav class="nav">
        <ul class="nav_menu">
          <li class="nav_menu_item">メニュー項目1</li>
          <li class="nav_menu_item">メニュー項目2</li>
          <li class="nav_menu_item">メニュー項目3</li>
          <li class="nav_menu_item">メニュー項目4</li>
        </ul>
      </nav>
    </header>
    <!-- コンテンツ -->
    <div class="content">
      <div class="content_item">
        <h2>コンテンツ1</h2>
        <p>この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。</p>
      </div>
    </div>
CSSをの「position: fixed;」を使用してヘッダーを固定表示させてみます。
/* CSSコード */
.header {
  background: #fff;
  display: flex;
  top: 0;
  height: 80px;
  padding: 10px;
  position: fixed;
  justify-content: space-between;
  width: 100%;
}
.nav_menu {
  display: flex;
  padding: 10px;
}
.nav_menu_item {
  margin-left: 20px;
}
.content {
  max-width: 1020px;
  margin: 0 auto;
}
.content_item {
  padding: 30px 0;
}
▼ブラウザ表示▼

なぜこのように、文字が重なって表示されてしまうのでしょうか?
詳しく見ていきましょう。
原因1:ヘッダーが浮いている
「position: fixed;」プロパティでヘッダーを固定したはずなのに、下の要素を重なってしまうのは「ヘッダーが浮いている」ことが原因です。
浮いているとは、文字通り宙に浮いているということで、floatプロパティと同様の状態になります。
この場合は、ヘッダーの下にpaddingで空白を作ってあげるだけで問題を解決できます。
/* CSSコード */
.content {
  max-width: 1020px;
  margin: 0 auto;
  padding-top: 80px;
}
上記のコードは、ヘッダーの下にある「content」クラスを指定しています。
▼ブラウザ表示▼

原因2:重なる順番の問題
「全部ではなく、一部だけヘッダーの上にテキストなどの要素が表示される」という時は、重なる順番が原因である可能性が高いです。
この場合は、z-indexプロパティで重なる順番を一番上に指定すれば解決できます。
/* CSSコード */
.header {
  z-index: 500;
}
positionプロパティを使いこなしてヘッダーを固定表示させよう!
今回は、positionプロパティを使ってヘッダーを固定表示させる方法について解説しました。
以下は、この記事のまとめです。
- ヘッダーを常時固定表示させるにはHTMLとCSSだけで十分
 - jQueryを使えばスクロールに合わせたヘッダーの固定表示を設定できる
 - positionプロパティのfixedを使う時は、必ず余白をつけよう!
 
ヘッダーやメニューバーの固定表示は、当たり前のように多くのWebサイトで利用されています。
レスポンシブ対応の際には、ハンバーガーメニューを使用するなど、ブラウザやWebサイトのデザインなどに合わせてピッタリの固定ヘッダーを設置してみてくださいね。