[CSS] ナビゲーションをレスポンシブでハンバーガーにする簡単な方法

この記事を書いてる現在世間はもとより世界も大変な状況になっている最中ですが割とマイペースに過ごぜる今これを機会にまた少しずつ当ブログを更新していくきっかけにできればと考えて「は」います。

以前書いた[CSS] レスポンシブなモーダルウィンドウを簡単に作るという記事が今なお多くのアクセスをいただいている記事なのですがレスポンシブに対応したギミック系処理は割と欲する情報なのかなと感じているしだいです。そこで今回はウェブサイトにはつきものであるグローバルナビゲーションを実装してみたいと思います。当ブログのこれ系シリーズでこだわっているクリックイベントでHTMLにClassセレクタを付与するのみをJavaScript の仕事とし表現はCSS に任せ”仕掛けと表現のすみわけ” をして進めてみたいと思います。結果パソコンで表示するときは通常のよくあるグローバルナビゲーションが表示され、画面の狭い(スマートフォン)場合にハンバーガーメニューによるナビゲーション表示に切り替わるようにしたいと思います。

仕様は以下としてみます。

  •  レスポンシブ対応
  •  PCビューのときはよくあるグローバルナビゲーションを表示
  •  SPビューのときはハンバーガーメニューを表示
  • ハンバーガーメニューをクリックしたらナビゲーションを表示
  • 合わせてナビゲーションの背景は薄暗くさせる

HTML はナビゲーションを構成する要素(#global)とその背景(#overlay)を用意します。ナビゲーションを構成する要素(#global)の内部にハンバーガーメニュー(.button)とナビゲーションアイテム(.items)が存在している構成になります。

<div id="global">
  <button class="button">
    <span> </span>
    <span> </span>
    <span> </span>
  </button>
  <nav class="items">
    <a href="#" class="item">メニュー No.1</a>
    <a href="#" class="item">メニュー No.2</a>
    <a href="#" class="item">メニュー No.3</a>
    <a href="#" class="item">メニュー No.4</a>
    <a href="#" class="item">メニュー No.5</a>
    <a href="#" class="item">メニュー No.6</a>
  </nav>
</div>
<div id="overlday"> </div>

JavaScript はハンバーガーメニュー(.button)をクリックしたらナビゲーションを構成する要素(#global)とその背景(#overlay)に .active を付与、再度ハンバーガーメニュー(.button)ないしナビゲーションの背景(#overlay)をクリックしたら上述で付与された .active が除去される定義になります。

$(document).ready(function() {
  $(".button, #overlday").on("click", function() {
    $("#global").toggleClass("active");
    $("#overlday").toggleClass("active");
  });
});

あとはCssでPCビューはハンバーガーメニュー(.button)とSPビューのみで利用するナビゲーションの背景(#overlay)を初期設定で非表示状態に、SPビューになるとハンバーガーメニュー(.button)が表示され逆にナビゲーションアイテム(.items)が非表示になる定義をしています。ナビゲーションを構成する要素(#global)に .active が付与されたら上述の非表示要素が表示されるような定義をしています。

#global {
  display: block;
  width: 100%;
  box-sizing: border-box;
  margin-top: 20px;
  background-color: #4285f4;
}
#global .button,
#overlday {
  display: none;
}
#global .items {
  display: flex;
  justify-content: center;
}
#global .items > .item {
  display: block;
  color: #fff;
  text-decoration: none;
  box-sizing: border-box;
  padding: 10px 20px;
  border-right: 1px solid #fff;
}
#global .items > .item:last-of-type {
  border-right: none;
}

@media only screen and (max-width: 768px) {
    #overlday {
      display: none;
      position: fixed;
      z-index: 9;
      left: 0;
      top: 0;
      right: 0;
      bottom: 0;
      background-color: rgba(0, 0, 0, .65);
    }
    #overlday.active {
      display: block;
    }
    #global {
      position: fixed;
      z-index: 10;
      left: 0;
      top: 0;
      text-align: right;
      margin-top: 0;
      background-color: transparent;
    }
    #global .button,
    #global .button > span {
      display: inline-block;
      transition: all .4s;
      box-sizing: border-box;
    }
    #global .button {
      position: relative;
      width: 40px;
      height: 30px;
      border: none;
      cursor: pointer;
      background: transparent;
      margin: 10px;
    }
    #global .button > span {
      position: absolute;
      left: 0;
      width: 100%;
      height: 4px;
      background-color: #4285f4;
      border-radius: 4px;
    }
    #global .button > span:nth-of-type(1) {
      top: 0;
    }
    #global .button > span:nth-of-type(2) {
      top: 13px;
    }
    #global .button > span:nth-of-type(3) {
      bottom: 0;
    }
    #global.active .button > span {
      background-color: #fff;
    }
    #global.active .button > span:nth-of-type(1) {
      transform: translateY(13px) rotate(-45deg);
    }
    #global.active .button > span:nth-of-type(2) {
      opacity: 0;
    }
    #global.active .button span:nth-of-type(3) {
      transform: translateY(-13px) rotate(45deg);
    }
    #global .items {
      display: none;
      flex-wrap: wrap;
      text-align: left;
      background-color: #4285f4;
    }
    #global.active .items {
      display: flex;
    }
    #global .items > .item {
      width: 100%;
      padding: 10px;
      border-right: none;
      border-bottom: 1px solid #fff;
    }
    #global .items > .item:last-of-type {
      border-bottom: none;
    }
}

実際のデモはこちら

ブラウザの横幅を縮めたり広げたりしたときに画面が広いときはよくあるグローバルナビゲーションが表示され、画面が狭いときはハンバーガーメニューにナビゲーションアイテムが畳まれることが体現できているかと思います。ナビゲーションアイテムにCSS アニメーションも付け加えるとよりリッチな表現で表示・非表示の演出ができそうですがこれはまた機会があれば記事にしたいと思います。

SPビューにおけるナビゲーションの扱いは色々なアイデアがあると思いますがソースコードの見通しをよく維持したい場合の参考になれば幸いです。

CSSに関するその他の記事

  • 2020.04.16
  • お仕事っぽいこと