cssでハンバーガーメニューを作成してみたよ

css

さてスマホでよく見るようなハンバーガーメニューですが、せっかくCSSでTransitionについて記事にしたので、ハンバーガーメニューでも作ってみようかと思います。
ネットで調べるといくつか定番?な作り方があるようですが今回自分が作ったのはやり方が違いました。笑 その違いも後で説明します

今回作るハンバーガーメニューの流れ

実際にCodepenで作成したサンプルですが、流れはこんな感じです。

  • 三本線(ハンバーガーのような形してるからこう呼ぶらしい)をクリックすると×印に変わるアニメーション
  • フェードインでメニューが全面に表示される。

といった流れにします。なおjQueryでクリックしたらTransitionアニメーションを実行させる為にクラスを追加する処理をしています。

See the Pen ハンバーガーメニュー by kiriyama (@kirikirimai) on CodePen.

各ソースコード

各ソースコードの説明をしていきますが、不要なものを省いていることもあるのでちゃんとしたコードはCodepenで確認可能です。

HTML


ハンバーガーメニューになる部分は「nav_hbg」としています。こちらはspanタグがハンバーガーメニューの横棒になるところです。
そして表示されるメニューは「nav_menu」としています。こちらは特に説明はいりませんね。

CSS(ハンバーガーメニュー)

#header #nav_hbg {
  position: fixed;
  top: 25px;
  right: 25px;
  cursor: pointer;
  z-index: 20;
}

#header #nav_hbg div 
  display: flex;
  flex-wrap: wrap;
  align-content: space-around;
  width: 40px;
  height: 40px;
  padding: 5px;
  border: 1px solid #fff;
  box-sizing: border-box;
}

#header #nav_hbg div span {
  width: 100%;
  height: 2px;
  background-color: #fff;
  transition: opacity 0.1s ease, transform 0.3s ease-in-out;
}

#header .clicked span:nth-child(1) {
  transform: translateY(10px) rotate(135deg);
}

#header .clicked span:nth-child(2) {
  opacity: 0;
}

#header .clicked span:nth-child(3) {
  transform: translateY(-10px) rotate(-135deg);
}

まずはハンバーガーメニューの部分から。
「#nav_hbg」はヘッダーに固定させたかったので「position:fixed」させています。あとはメニューが全面に表示された時に隠れてしまわないように「z-index」の値を設定しています。

「#nav_hbg div」ですが、幅や高さ、枠のボーダーの設定をしています。余白は5pxとして三本線とのスペースです。
そして三本線のレイアウトの設定として「display:flex」としています。すると普通は子要素のspanタグ(三本線のタグ)が横並びになってしまうのですが、spanタグの幅を100%にして「flex-wrap:wrap」することで縦並びになります。縦に並べて三本線を均等にしたいので「align-content: space-around」して縦軸で均等に配置します。
この「align-content」 プロパティは、縦方向(交差軸方向)の揃え位置を指定する際に使用します。横方向の場合は「justify-content」プロパティになります。
実はflexをわざわざ使用したのは縦方向に均等に設定したい為です。ほかのネット上のやり方だと、三本線となる要素(spanタグ)を絶対配置にして、topプロパティで位置を調整するやり方が多かったのですが、大枠に対して三本線の位置を細かく設定するのがめんどくさかったので、高さと幅が変わっても自動的に調整するように今回は「 align-content 」を選びましたが、どっちでも構わないと思います。他には「:before」「:after」の疑似要素で三本線の二本を再現している例もありました。

三本線となるspanタグの設定ですが、幅は100%で線の太さを2pxとし線の色をbackground-colorで設定しています。そしてクリックしたら線を「×」にする Transition アニメーションの設定で真ん中の線は非表示にしたいので「「opacity」と上と下の線は回転(rotate)と位置の調整(translateY)を「transform」の設定をしています。今回はアニメーションのスピードが違うのでTransitionの設定で分けていますが、スピードが同じでいいなら「all」もしくは書かなくても大丈夫です。

クリックした後は、jQueryで「clicked 」というクラスを追加する事をやっていますが、クラスが追加された時に三本線それぞれを「:nth-child」で設定しています。真ん中の線は非表示にしたいので「opacity:0」でふわっと消えていきます。上の下の線に関しては、transformのrotateプロパティで135度回転させています。135度のほうが回転が心地よい気がしただけで、45度でも「×」になります。
また三本線のそれぞれの線とのスペースや幅や高さによってクリックしても綺麗な「×」にならない場合があるので、そこはtransoformのtranslateYプロパティで上下(縦方向)の位置を調整して綺麗な「×」になるように調整しています。

CSS(ナビゲーションメニュー)

/* ナビゲーションのメニュー */
#header #nav_menu {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  opacity: 0;
  visibility: hidden;
  transition: all 0.4s ease;
  z-index: 10;
  background-color: #333;
}

#header #nav_menu.opened {
  visibility: visible;
  opacity: 1;
}

クリックされた後に表示されるメニューですが今回は全面に表示させたいので、「#nav_menu」の設定で「position:fixed」で固定しています。ただハンバーガーメニューより上に表示されると消せなくなるので「z-index」でハンバーガーメニューの下のレイヤーにしています。
また非表示にさせる時に「opacity:0」してますが、「visibility: hidden」にしないとナビゲーションのリンクが反応してしまうので気をつけましょう。
後は表示させるアニメーションの設定で「transition」の設定をしています。

こちらもクリックした後は「opened」のクラスが付与されますが、「visibility: visible」で表示させることを忘れずに。

JQuery

$("#nav_hbg div").on("click", function() {

    $(this).toggleClass("clicked");
    $("#nav_menu").toggleClass("opened");
}

CSSの設定の後は、実際にtransitionを実行させる為にクラスの付与をします。
クリックした後、もう一度クリックすることになるので、toggleClassメソッドでハンバーガーメニューとナビゲーションメニューにクラスを追加・削除の処理をしています。
*思えばここの処理は「clicke」「opend」のどちらかのクラスだけでもよかったですね(笑)

レスポンシブ対応について

さて、レスポンシブ対応に関してですが、よく幅などを「%」で設定する事もありますが、ハンバーガーメニューの場合は幅が「px」で設定されてないと上手くいきませんでした。
なのでレスポンシブ対応させる場合は、ブレイクポイントの設定で都度、pxでサイズ変更するなどして対応するほうがよさそうな気がします。
*もし他に方法があれば知りたいですが、、

まとめ

さて、今回はtransitionを利用してハンバーガーメニューを作成しました。
割とスマホページだとこのメニューは目にすることが多いので覚えておくいいですね。