一から始めるWeb制作 #12〜ナビゲーションの基礎その2・ハンバーガーメニュー

ハンバーガー イメージ

ハンバーガー イメージ

今回は、モバイルファーストインデックスに必須の「ハンバーガーメニュー」について。

ハンバーガーメニューは、モバイルデバイスにおける、グローバールメニューの表示形式のひとつで、その形がハンバーガーに似ていることに由来する。

筆者の会社ウェブサイトでも採用しているハンバーガーメニューをより簡素化したもので、javascriptを使わずHTML+CSSで制作してある。

前回紹介したグローバルナビゲーションとあわせて、ウェブ制作の参考にしていただきたい。

ハンバーガーメニューの全体像

最初に、全体のイメージ把握のため、デモサイト・HTML・CSSを掲載しておこう。CSSは、前回解説したグローバルナビゲーションや、その他部分は省略してある。

ハンバーガーメニューは、スマートフォン(タテ)の場合のみ表示され、ヨコにしたときやタブレットでは、パソコン表示と同じグローバルナビゲーションを表示するよう、設定してある。

デモサイトのメニュー項目ひとつひとつが短い単語のため、スマートフォンを横にしてもパソコン同様表示できるからだ。

デモサイト3

HTML全体

<!doctype html>

<html lang="ja">

  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ざっくりLinux!</title>
    <meta name="description" content="Linuxのあれこれをざっくりと書いています">
    <link rel="stylesheet" href="css/style-demo-3.css">
  </head>

  <body>
    <header>
      <div>
        <a href="demo-3.html"><img id="logo" src="images/Zakkuri.png" alt="Site Logo"></a>
      </div>

      <!-- モバイル用ハンバーガーメニュー -->
      <div class="hamburger-menu">
        <input type="checkbox" id="menu-btn-check">
        <label for="menu-btn-check" class="menu-btn"><span></span></label>
          <div class="menu-content">
            <ul>
              <li>
                <a class="nav_menu_li" href="demo-3.html">Home</a>
              </li>
              <li>
                <a class="nav_menu_li" href="Debian/index.html">Debian</a>
              </li>
              <li>
                <a class="nav_menu_li" href="Ubuntu/index.html">Ubuntu</a>
              </li>
              <li>
                <a class="nav_menu_li" href="RHEL/index.html">RHEL</a>
              </li>
              <li>
                <a class="nav_menu_li" href="OSS/index.html">OSS</a>
              </li>
            </ul>
          </div>
      </div>
      <!-- ここまで モバイル用ハンバーガーメニュー -->
    </header>

    <div class="container"><!-- 大枠のコンテナ -->
      <!-- PC用グローバルナビゲーション -->
      <nav class="pc">
        <ul class="pc">
          <li>
            <a href="demo-3.html">Home</a>
          </li>
          <li>
            <a href="Debian/index.html">Debian</a>
          </li>
          <li>
            <a href="Ubuntu/index.html">Ubuntu</a>
          </li>
          <li>
            <a href="RHEL/index.html">RHEL</a>
          </li>
          <li>
            <a href="OSS/index.html">OSS</a>
          </li>
        </ul>
      </nav>
      <!-- ここまでPC用グローバルナビゲーション -->

      <div class="main-container"><!-- メインコンテナ(横幅設定) -->

        <h1>ざっくりLinux!</h1>
        <p class="title-discript">Linuxのあれこれをざっくりと書いています</p>

        <img class="imgcenter" src="images/Linux.jpg" alt="Linux イメージ">

        <div class="index">
        <p>【目次】</p>
          <ul class="mokuji">
            <li>
              <a href="Debian/index.html">Debianに関する記事一覧</a>
            </li>
            <li>
              <a href="Ubuntu/index.html">Ubuntuに関する記事一覧</a>
            </li>
            <li>
              <a href="RHEL/index.html">RHELに関する記事一覧</a>
            </li>
            <li>
              <a href="OSS/index.html">OSSに関する記事一覧</a>
            </li>
          </ul>
        </div>
      </div><!-- ここまでメインコンテナ(横幅設定) -->

      <footer>
        <p class="footmenu"><a href="demo-3.html">Home</a> | <a href="#">Sitemap</a> | <a href="#">About Us</a> | <a href="#">Contact Us</a></p>

        <p class="copyright">Copyright ©ざっくりLinux! All rights reserved.</p>
      </footer>
    </div><!-- ここまで大枠のコンテナ -->

  </body>
</html>

CSS

@charset "utf-8";

/* その他部分のCSSは省略 */

/* スマートフォン用 */
@media screen and (max-width: 599px) {
  .pc {
    display: none;
  }

  /* ハンバーガーメニューボタン */
  .menu-btn {
      position: fixed;
      top: 5px;
      right: 8px;
      display: flex;
      height: 60px;
      width: 60px;
      justify-content: center;
      align-items: center;
      z-index: 90;
  }
  .menu-btn span,
  .menu-btn span:before,
  .menu-btn span:after {
      content: '';
      display: block;
      height: 4px;
      width: 35px;
      border-radius: 3px;
      background-color: #a9a9a9;
      position: absolute;
  }
  .menu-btn span:before {
      bottom: 13px;
  }
  .menu-btn span:after {
      top: 13px;
  }

  #menu-btn-check:checked ~ .menu-btn span {
      background-color: rgba(255, 255, 255, 0); /*メニューオープン時は真ん中の線を透明にする*/
  }
  #menu-btn-check:checked ~ .menu-btn span::before {
      bottom: 0;
      transform: rotate(45deg);
  }
  #menu-btn-check:checked ~ .menu-btn span::after {
      top: 0;
      transform: rotate(-45deg);
  }

  #menu-btn-check {
      display: none;
  }
  /* ここまでハンバーガーメニューボタン */

  /* メニューリスト */
  .menu-content {
      width: 100%;
      height: 100%;
      position: fixed;
      top: 0;
      left: 0;
      z-index: 80;
      background-color: #fff;
  }
  .menu-content ul {
      padding: 70px 10px 0;
  }
  .menu-content ul li {
      border-bottom: solid 1px #a9a9a9;
      list-style: none;
  }
  .menu-content ul li a {
      display: block;
      width: 90%;
      font-size: 15px;
      box-sizing: border-box;
      color:#a9a9a9;
      text-decoration: none;
      padding: 9px 15px 10px 0;
      position: relative;
  }
  .menu-content ul li a::before {
      content: "";
      width: 7px;
      height: 7px;
      border-top: solid 2px #a9a9a9;
      border-right: solid 2px #a9a9a9;
      transform: rotate(45deg);
      position: absolute;
      right: 11px;
      top: 16px;
  }

  .menu-content {
      width: 100%;
      height: 100%;
      position: fixed;
      top: 0;
      left: 100%; /*leftの値を変更してメニューを画面外へ*/
      z-index: 80;
      background-color: #fff;
      transition: all 0.5s; /*アニメーション設定*/
  }

  #menu-btn-check:checked ~ .menu-content {
      left: 10%; /*メニューを画面内へ*/
  }
  /* ここまでメニューリスト */
}

/* タブレット用 */
@media screen and (min-width: 600px) {
  .hamburger-menu {
    display: none;
  }
}

/* PC用 */
@media screen and (min-width: 1025px) {
  .hamburger-menu {
    display: none;
  }
}

ハンバーガーメニューのHTML

ハンバーガーメニューのHTMLといっても、グローバルナビゲーションであることに変わりはない。

今回解説するのは、パソコン用・モバイル用別々のナビゲーションのHTMLを用意し、デバイスによって表示・非表示にする方法。

前回紹介したグローバルナビゲーションは、パソコン及びスマートフォン(ヨコ)・タブレットの時だけ表示されるようにし、今回新たにheader部分に追加したナビゲーションは、スマートフォン(タテ)の時だけ表示される。

header内のナビゲーションには、ハンバーガーメニューのボタンを用意する。

    <header>
      <div>
        <a href="demo-3.html"><img id="logo" src="images/Zakkuri.png" alt="Site Logo"></a>
      </div>

      <!-- モバイル用ハンバーガーメニュー -->
      <div class="hamburger-menu">
        <!-- 以下2行がハンバーガーメニューボタンになる -->
        <input type="checkbox" id="menu-btn-check">
        <label for="menu-btn-check" class="menu-btn"><span></span></label>

          <!-- ハンバーガーメニューのリストアイテム -->
          <div class="menu-content">
            <ul>
              <li>
                <a class="nav_menu_li" href="demo-3.html">Home</a>
              </li>
              <li>
                <a class="nav_menu_li" href="Debian/index.html">Debian</a>
              </li>
              <li>
                <a class="nav_menu_li" href="Ubuntu/index.html">Ubuntu</a>
              </li>
              <li>
                <a class="nav_menu_li" href="RHEL/index.html">RHEL</a>
              </li>
              <li>
                <a class="nav_menu_li" href="OSS/index.html">OSS</a>
              </li>
            </ul>
          </div>
      </div>
      <!-- ここまで モバイル用ハンバーガーメニュー -->
    </header>

ハンバーガーメニューボタンのHTMLは、この時点では何を書いているのかわからないと思うが、ここをCSSでナビゲーションと連動して動くようにしていく。

ハンバーガーメニューのCSS解説

ここからは、ポイントごとに分けて解説していこう。

デバイスごとに表示・非表示を分ける

上述の通り、デバイスごとにメニューの表示を分けるため、以下をCSSに記載しておく。それぞれのクラスは、

  • スマートフォン(タテ)用ナビゲーション(ボタンを含む):hamburger-menu(divのクラス)
  • パソコン及びスマートフォン(ヨコ)・タブレット用ナビゲーション:pc(navのクラス)
/* スマートフォン用 */
@media screen and (max-width: 599px) {
  .pc {
    display: none;
  }

/* タブレット用 */
@media screen and (min-width: 600px) {
  .hamburger-menu {
    display: none;
  }
}

/* PC用 */
@media screen and (min-width: 1025px) {
  .hamburger-menu {
    display: none;
  }
}

「pc」クラスは、599ピクセル以下で非表示になるよう、display:noneとしておく。それ以外のデバイスでは、指定していないので表示される。

反対に、「hamburger-menu」クラスは、599ピクセル以下では指定しないため表示され、600ピクセル以上でdisplay:noneで非表示にしておく。

メニューボタンの全体設定

今回、ハンバーガーメニューは、ヘッダー右寄せで配置する。左側に配置する場合でも、このCSSをアレンジすることでできるだろう。

  .menu-btn {
      position: fixed; /*ポジションを固定*/
      top: 5px; /*ボタン上の余白*/
      right: 8px; /*ボタン右の余白*/
      display: flex; /*ヘッダー内で横並び*/
      justify-content: center; /*flexboxコンテナのメイン軸の中心から配置する*/
      align-items: center; /*flexboxコンテナのクロス軸にあわせて中央に配置する*/
      height: 60px; /*ボタンの高さ*/
      width: 60px; /*ボタンの幅*/
      z-index: 90; /*常に最前面に来るように*/
  }

justify-contentは、flexboxアイテムを配置する際に、開始点や終了点、中心からの配置を可能にする属性。メイン軸(flexアイテムを配置する方向)を指定する。

align-itemsも同様で、flexboxアイテムのクロス軸(メイン軸に対して垂直方向の軸)に沿って配置する属性。

どちらも、必ず、display:flex or inline-flexとともに使用する。

難解な説明だが、要はハンバーガーメニューボタンの位置を決めるものだ。

spanタグで3本線を作る

ハンバーガーの3本線は、空白のspanタグにデザインを加え、アニメーションのような動作のメニューを書いていく。

  .menu-btn span,
  .menu-btn span:before,
  .menu-btn span:after {
      content: ''; /*spanに文字も画像も入れない*/
      display: block;
      height: 4px; /*各線の幅(厚さ)*/
      width: 36px; /*各線の長さ*/
      border-radius: 3px; /*各線に丸みをつける*/
      background-color: #a9a9a9; /*各線の色*/
      position: absolute;
  }
  .menu-btn span:before {
      bottom: 12px;
  }
  .menu-btn span:after {
      top: 12px;
  }

各数字については、以下の通り。

ハンバーガーメニューボタンの全体で、横幅・高さともに60pxに設定してある。

3本線の横幅を36pxとしたので、横の余白はそれぞれ12px×2=24px。

これをもとに、縦位置を決めていく。

線の幅(厚さ)は4px×3本=12px、横幅36pxと縦幅を合わせるため、

60-12-36=24px、これを上下の余白とするので、最後に「bottom: 12px; top: 12px;」とした。

3本線のアニメーション

メニューボタンの3本線ができたので、これにCSSでアニメーション的な動きをつける。

ボタンをタップしたとき、3本線がバツ(×)の形になり、メニューリストがスライドするようにするもの。

HTMLで作った、空のspanタグ内に3本線を形成し、そこに動きをつけるCSSは以下の通り。

  #menu-btn-check:checked ~ .menu-btn span {
      background-color: rgba(255, 255, 255, 0); /*メニューオープン時は真ん中の線を透明にする*/
  }
  #menu-btn-check:checked ~ .menu-btn span::before {
      bottom: 0;
      transform: rotate(45deg);
  }
  #menu-btn-check:checked ~ .menu-btn span::after {
      top: 0;
      transform: rotate(-45deg);
  }

最初は、メニューを開いた時、3本線のうち真ん中の1本を透明にして、上下2本で動きをつけるようにするもの。

transform: rotate(45deg)は、要素を二次元平面上の特定の点を中心に、形を崩さずに回転させて変形するCSS。

開くときに45度(45deg)回転し、閉じるときにマイナスで45度(-45deg)回転する。

HTML4.01では画像ファイルを使うしかなかった、ブラウザ上のイメージ表示が、HTML5ではHTMLとCSSで画像を表示し、自由に回転して表示することができるので、覚えておくと便利だ。

これでハンバーガーメニューボタンが完成した。

説明が前後するが、HTMLにて書いた、

        <input type="checkbox" id="menu-btn-check">

は、ボタンがタップされたかどうかをチェックボックスで判断するというもの。実際は表示不要なので、

  #menu-btn-check {
      display: none;
  }

で打ち消しておく。

スライドするメニューリストの実装部分

最後は、ハンバーガーメニューボタンをタップすると、スライドして出てくるメニューリストのCSS。

  .menu-content {
      width: 100%;
      height: 100%;
      position: fixed;
      top: 0;
      left: 0;
      z-index: 80;
      background-color: #fff;
  }
  .menu-content ul {
      padding: 70px 10px 0;
  }
  .menu-content ul li {
      border-bottom: solid 1px #a9a9a9;
      list-style: none;
  }
  .menu-content ul li a {
      display: block;
      width: 90%;
      font-size: 15px;
      box-sizing: border-box;
      color:#a9a9a9;
      text-decoration: none;
      padding: 9px 15px 10px 0;
      position: relative;
  }
  .menu-content ul li a::before {
      content: "";
      width: 7px;
      height: 7px;
      border-top: solid 2px #a9a9a9;
      border-right: solid 2px #a9a9a9;
      transform: rotate(45deg);
      position: absolute;
      right: 11px;
      top: 16px;
  }

menu-cotent、menu-content ul、menu-content ul li、menu-content ul li a、menu-content ul li a::beforeまでは、今までの説明で事足りるので省略。

各装飾内容は、自身の構想内容に書き換えてもらいたい。

ここまででは、メニューリストは常に出ている状態のため、menu-contentのCSSを以下のとおり追加・変更する。

  .menu-content {
      width: 100%;
      height: 100%;
      position: fixed;
      top: 0;
      left: 100%; /*leftの値を変更してメニューを画面外へ*/
      z-index: 80;
      background-color: #fff;
      transition: all 0.5s; /*アニメーション設定*/
  }

最後に、メニューボタンをタップしたら、メニューリストがスライドして出てくるよう、CSSを追加する。全面にメニューリストが出るのは、個人的に好きではないので、左10%残してスライドするように調整しておいた。

  #menu-btn-check:checked ~ .menu-content {
      left: 10%;
  }

この記事のまとめ

デモサイト3で表示される内容を、HTMLとCSSに分けて説明した。

一般的なハンバーガーメニューは、3本線の画像を別途用意したり、アニメーション的な動きにjavascriptや、jqueryを使っているものが多いが、このように一からHTMLとCSSで書くことは、

  • HTMLとCSSの勉強になる
  • なるべくjavascriptを使わないことで、ページスピードが速くなり、SEO的にも良い

といった利点がある。

ここに書いた内容も、ネット上のさまざまな情報をもとに制作したもの。なので、ウェブ制作はネットをもとにした独学で、十分に習得することが可能だ。

【本で学習したい人はコレ】

コメント