「HTML」と「CSS」のみで実装する ハンバーガーメニュー

【基本編】ハンバーガーメニュー 「HTML」と「CSS」のみで実装する

スマートフォンサイトに限らず、PCサイズのサイトにも使われることが多くなった、三本線でメニューボタンを表すハンバーガーメニュー。Javascriptを使わずに、「HTML」のinput要素と「CSS」だけで実装する方法について確認していきたいと思います。

ハンバーガーメニューとは何か?

ハンバーガーメニューとはどういった形式のものを指すのでしょうか。ハンバーガーの名前の由来は、三本線でメニューボタンを表したものが、そのシルエットがハンバーガーのバンズの部分に似ているところから呼ばれるようになったそうですが、動作的にまとめると次のようになります。

  1. ハンバーガーボタンをクリックする
  2. 隠れていたメニューリストが表示される(ドロワーメニュー)
  3. ドロワーメニューが表示されると同時に、三本線が×に変化する
  4. ×ボタンをクリックするとメニューが隠れる、×ボタンが再び三本線に戻る

つまり、部分的に分けると、「ハンバーガーの三本線がクリック動作によって変化するボタン」部分と、「ドロワーメニューの表示・非表示」部分の2つのになります。

ドロワーメニューの表示については、ページ全体や、ある程度の部分をレイヤー的に覆う形でフェイドインやスライドインするタイプが多いですが、画面全体が横方向(もしくは縦方向)にずれて、画面の外に隠れていたメニューが表示されるオフキャンバスと呼ばれる方法もあります。

今回は、比較的簡単に実装可能な前者のタイプで設定を行っていきます。

HTMLのコーディング

HTMLマークアップを行う前に確認しておきたいのが、inputとlabelの関係性です。今回のハンバーガーメニューの制御は、ボタンをクリックするというイベントがトリガーとなるので、Javascriptであれば、onclickイベントを使用するところですが、HTMLのinput要素のチェックボックスを使用しても同じようなことができます。

input要素のチェックボックスを利用する

チェックボックスをクリックしてチェックが入ると、input要素にchecked属性が付与されます。この仕様を利用して、CSSでcheckedが付いた場合にハンバーガーボタンと、ドロワーメニューのスタイルを設定し、またアニメーションを付けることで、さきほどの①~④のハンバーガーメニューの動作要件を実現していきます。

<input type="checkbox" checked> 
<!--チェックボックスにチェックが入るとchecked属性がつく -->

label要素を紐づけてボタンにする

input要素には、for属性でテキストなど項目名を紐づけることができるlabel要素がありますが、この関係性を利用して、ハンバーガーのボタン部分をlabel要素で作成していきます。input要素をそのままボタン部分として、スタイルをつけるには自由度が少ないので、label要素を使用して作成し、input要素自体は機能面の利用がメインとなるので、あとで見えないようにCSSで非表示にしてしまいます。

<input id="check_input" type="checkbox">
<label id="menu_btn" for="check_input"></label>
<!-- label要素のfor属性にinput要素のid名を指定することで、紐づけることができ、
label要素部分をクリックしてもinput要素にチェックが入ります。 -->

ハンバーガーメニュー(ドロワーメニュー)のHTMLマークアップ

ハンバーガーメニュー部分のHTMLは次のようになります。

<div id="drawer">
      <input id="check_input" type="checkbox">
      <label id="menu_btn" for="check_input"> <!-- ハンバーガーボタン部分 -->
          <span></span>
      </label>
      <label id="drawer_back" for="check_input"></label> <!-- ドロワーメニューの背景部分 これもinputと紐づける -->

      <div id="menu_cont"> <!-- ドロワーメニュー部分 -->
          <ul>
              <li><a href="">HOME</a></li>
              <li><a href="">COMPANY</a></li>
              <li><a href="">ABOUT</a></li>
              <li><a href="">ACCESS</a></li>
              <li><a href="">CONTACT</a></li>
           </ul>
      </div>
</div>

6行目:さきほどの、ハンバーガーボタンのlabel要素にプラスして、クリックしたら表示されるドロワーメニューの外の背景部分(コンテンツを覆う部分)もlabel要素で作成したいと思います。こちらも、for属性で同じinput要素と紐づけることで、ハンバーガーボタンを押さなくても外の背景部分をクリックするとチェックが外れドロワーメニューが非表示となる動きとなり、ユーザービリティの向上が図れます。

8行目:ドロワーメニューの本体部分となります。input要素にcheckedが入ると表示されます。

こちらをheader要素に設置します。

CSSのスタイリング

次はCSSです。まずは、ハンバーガーボタンや、ドロワーメニューのスタイルをつけていきましょう。

ハンバーガーボタンの三本線はクリックしたらアニメーションさせるので、span要素とbefore、after疑似要素で作成しておきます。

/* input非表示 */
        #check_input {
            display: none;
        }

/* ハンバーガーボタン */
        #menu_btn {
            position: fixed;
            top: 30px;
            right: 30px;
            height: 60px;
            width: 60px;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 100;
            background-color: #fff;
            cursor: pointer;
        }
       /* 三本線*/
        #menu_btn span,
        #menu_btn span::before,
        #menu_btn span::after {
            content: "";
            display: block;
            position: absolute;
            height: 3px;
            width: 25px;
            border-radius: 3px;
            background-color: #CE5D8B;
            transition: all 0.5s cubic-bezier(0.075, 0.82, 0.165, 1); /*アニメーションのイージングも設定しておく*/
        }
        #menu_btn span::before {
            bottom: 8px;
        }
        #menu_btn span::after {
            top: 8px;
        }

/* ドロワーメニュー */
        #menu_cont {
            position: fixed;
            top: 0;
            left: 100%; /*left 100%で画面の外に出しておく*/
            width: 80%;
            height: 100%;
            background: #fff;
            z-index: 90;
            transition: all 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
        }

        /* ドロワーメニュー外の背景 */
        #drawer_back {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 80;
        }

        /* メニューリストの装飾 */
        #menu_cont ul {
            padding: 20% 10% 0
        }
        #menu_cont ul li {
            list-style: none;
        }
        #menu_cont ul li a {
            display: block;
            width: 100%;
            padding: 10px;
            margin: 5px;
            color:#CE5D8B;
            text-decoration: none;
        }
        #menu_cont ul li a:hover {
            opacity: 0.7;
        }

間接セレクタについて

今回の重要な部分として、input要素のchecked属性がついたらスタイルが変更される必要がありますが、こちらは、CSSの間接セレクタ(~)を使用して実現していきます。

間接セレクタとは、同じ階層に属していて、指定した要素の後以降に位置している要素を対象としたものです。ですので、HTML上では、ハンバーガーボタンや、ドロワーメニューなど、checkedが入ると変更される部分は、input要素と同じ階層にしておく必要があります。(HTMLを確認する

CSSのスタイルの変更は次のようになります。

/*ハンバーガーボタン*/
        /* クリックされたら三本線が×に変化する */
        #check_input:checked ~ #menu_btn span {
            background-color: transparent; 
        }
        #check_input:checked ~ #menu_btn span::before {
            bottom: 0;
            transform: rotate(45deg);
        }
        #check_input:checked ~ #menu_btn span::after {
            top: 0;
            transform: rotate(-45deg);
        }

/*ドロワーメニュー*/
        /* クリックされたらドロワーメニュー表示 */
        #check_input:checked ~ #menu_cont {
            left: 20%;
        }
        #check_input:checked ~ #drawer_back {
            display: block;
        }

クリックされたら三本線が×に変化する部分

3~6行目:三本線の真ん中は透明に、7行目以降:上と下の線は、縦の位置を調整し、45度回転で×になる

ドロワーメニューの表示

17~19行目:ドロワーメニュー本体のleft位置を変更することで、画面外から左にスライドインするアニメーションになります。

20~22行目:ドロワーメニューの外の背景を表示することで、メインコンテンツのクリック誤動作の防止と、メニュー外を押してもドロワーが非表示になります。

CSSをまとめると次になります。

/* input非表示 */
        #check_input {
            display: none;
        }

/* ハンバーガーボタン */
        #menu_btn {
            position: fixed;
            top: 30px;
            right: 30px;
            height: 60px;
            width: 60px;
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 100;
            background-color: #fff;
            cursor: pointer;
        }
       /* 三本線*/
        #menu_btn span,
        #menu_btn span::before,
        #menu_btn span::after {
            content: "";
            display: block;
            position: absolute;
            height: 3px;
            width: 25px;
            border-radius: 3px;
            background-color: #CE5D8B;
            transition: all 0.5s cubic-bezier(0.075, 0.82, 0.165, 1); /*アニメーションのイージングも設定しておく*/
        }
        #menu_btn span::before {
            bottom: 8px;
        }
        #menu_btn span::after {
            top: 8px;
        }

        /* クリックされたら三本線が×に変化する */
        #check_input:checked ~ #menu_btn span {
            background-color: transparent; 
        }
        #check_input:checked ~ #menu_btn span::before {
            bottom: 0;
            transform: rotate(45deg);
        }
        #check_input:checked ~ #menu_btn span::after {
            top: 0;
            transform: rotate(-45deg);
        }

/* ドロワーメニュー */
        #menu_cont {
            position: fixed;
            top: 0;
            left: 100%; /*left 100%で画面の外に出しておく*/
            width: 80%;
            height: 100%;
            background: #fff;
            z-index: 90;
            transition: all 0.5s cubic-bezier(0.075, 0.82, 0.165, 1);
        }

        /* ドロワーメニュー外の背景 */
        #drawer_back {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.5);
            z-index: 80;
        }

        /* メニューリストの装飾 */
        #menu_cont ul {
            padding: 20% 10% 0
        }
        #menu_cont ul li {
            list-style: none;
        }
        #menu_cont ul li a {
            display: block;
            width: 100%;
            padding: 10px;
            margin: 5px;
            color:#CE5D8B;
            text-decoration: none;
        }
        #menu_cont ul li a:hover {
            opacity: 0.7;
        }

        /* クリックされたらドロワーメニュー表示 */
        #check_input:checked ~ #menu_cont {
            left: 20%;
        }
        #check_input:checked ~ #drawer_back {
            display: block;
        }

コードサンプル

See the Pen hamburder menu by web-basic-archive (@web-basic-archive) on CodePen.

ハンバーガーボタンのデザイン、ドロワーメニューの表示アニメーションは、他にもいろいろなタイプがありますので、次の機会にご紹介していきたいと思います。

参考にしたサイト

【コピペで簡単】ハンバーガーメニューをCSSだけで作る方法

Follow me!