🐕

VanillaJSでハンバーガーメニューを実装しよう

2022/11/07に公開

introduction

VanillaJSというのはなんのデコレーションもされていないバニラアイスクリームのように、どのフレームワークにも依存しないJSのことをいう。つまりデフォルトのJSなのだが、こう呼ぶとかっこいいのでこうよんでいる。今回はみんな大好きハンバーガーメニューについて実装していこうと思う。今回もこの記事を書く理由は、仕事で必要になったから。そのため、0から学んでいく過程をそのまま記事として理解を深めようということになる。備忘録みたいな感じになってしまうので、そのへんは了承してほしい。そして、今回からはcodepenを利用して書いていくのでよりわかりやすい記事になるのではないかと予想する。ほないくで^^

トグルボタンの実装

まずはボタンの実装から。ボタンによって、ハンバーガーメニューが表示されるかどうかをかえられるようにする。実装の手順としては、まずは閉じているデザインの実装→開いたボタンの実装→アニメーションの実装となる。ボタンの実装は、動くウェブデザイン手帳さんが非常に作例豊富に解説してくれているので、これを参考にする。
https://coco-factory.jp/ugokuweb/move01-cat/humbugermenu/

まずは閉じているデザインと開いたボタンの実装から。

document
 <div class="openbtn1">
   <span></span>
   <span></span>
   <span></span>
</div>

また、今回はscssで記述していくが、nth-of-typeを用いる場合は1段階ネストを深くしなくてはならない。これは以下のサイトを参考にした。
https://qiita.com/yusukeyamane/items/f642b8df85b1d682d147

design
@charset "utf-8";

.openbtn1{
  position: relative;
  background:#57a2c7;
  cursor: pointer;
  width: 50px;
  height:50px;
  border-radius: 5px;
  span{
    display: inline-block;
    transition: all .4s;
    position: absolute;
    left: 14px;
    height: 3px;
    border-radius: 2px;
  background: #fff;
    width: 22px;
    &:nth-of-type(1){
      top:15px; 
    }
    &:nth-of-type(2){
      top:23px; 
    }
    &:nth-of-type(3){
      top:31px; 
    }
  }
  &.active{
    span{
      &:nth-of-type(1){
        top: 18px;
        transform: translateY(6px) rotate(-45deg);
        width: 22px;
      }
      &:nth-of-type(2){
        opacity: 0;
      }
      &:nth-of-type(3){
      top: 30px;
      transform: translateY(-6px) rotate(45deg);
      width: 22px;
      }
    }
  }
}


/*========= レイアウトのためのCSS ===============*/

body{
  background:#f3f3f3;
    padding:20px;
}

トグルボタンのJSの実装に関しては、jQueryと同様にトグル操作が非常に簡単に利用することが出来る。
これには、以下のサイトが参考になった。まずは要素の取得、そしてイベントハンドラーの設定をしてから、関数の記述を行うのはもうわかっているんじゃないかな。
https://wemo.tech/2101

design
const btn = document.getElementsByClassName('openbtn01')[0];
btn.addEventListener('click',function(){
  this.classList.toggle('active');
})

これでトグルボタンの実装は完璧だな。

メニューを表示する方法

次にしないといけないのは、トグルボタンのオンオフに合わせてメニューを表示するのか、非表示にするのかを対応させなくてはならないということだ。
よく、ヘッダーなどに表示するメニューのことをグローバルメニューを呼ぶが、そのメニューは主にハンバーガーメニューにされることが多い(のは今の世代にとっては当たり前なんだけどね。一応)。
必要なのは、left:-120%にすることによって要素を一時的に見せなくするということ。そういえば要素ってはみ出したら横に余分に表示されちゃうんじゃないの??とかまじでクソ適当なことを思ってたんだけと、これは"そもそも"の勘違いが多いので、ひとつひとつ丁寧に解消しておこう。これから喋る内容は主に未来の自分用に書いているので、見るのめんどくせーって人とかはとばして次の実装部分にうつってね。

要素のはみ出しとは

自分が問題にしているのは、以下のような問題。初学者がよく当たる問題として、box-sizingがborder-boxにされていないことにより起こるんだ〜って、webcoderが必ず通るであろう道。自分はその原因を全然究明してなかったので、いましよう、そうしようとおもったわけ。
https://ginpen.com/2012/12/05/css-box-model/

このサイトが問題にしているのは結局、"box-sizingがborder-boxが指定されていないこと"よりも"要素がはみ出されている"ことによって生じたのだと考えるほうが本質的っぽいんだよな。じゃあどこからはみ出しているのかというと、html要素からなわけで、もう1階層落としてbodyタグからのはみ出しと考えてもいい。webとしては表示したいのはコンテンツ全てなわけで、その意志からスクロールをしてでも表示をしたいんだってなるんだな。じゃあどうやってはみださないようにするのか?そのためには2つ方法があるみたい。

・absoluteの場合
positionにabsoluteを設定しても、結局は要素の一つとして考えられるので、右には要素がはみ出してしまう。しかし実は、左側には要素のはみ出しは行われない。それはもともとwebのコンテンツが左から右西線が流れることに由来するのではないかと思うが、とにかくabsoluteにおいては左にはみ出しても要素ははみ出さない。

・fixedの場合
positionにfixedを設定した場合には、ドキュメントフローからも、そもそもドキュメントの構造からも外に飛び出て、固定された一つの要素として扱うので、そもそもはみ出しとかいう概念がない。そのため、自由度の高いまま要素を隠したりすることが出来るのがすごいポイントだ。ただ、これに関してはSEO的にどうかと言われると微妙なところでもある。まぁ以下のサイトを見てみると、切り替え表示によって表示できるなら大丈夫っぽいので、今回はSEO的に大丈夫と考えても良さそうだ。
https://blogger-learning-rab.blogspot.com/2020/09/item-hide.html

実際の実装

以下のサイトとjs以外はほぼ同じ実装になるため紹介は省く。JSはボタンのトグルと対応してactiveをつけてやればそれでいい。注意しなくてはいけないのは、ページ内リンクの場合にはナビゲーションを非表示にしなくてはならないので、classを除去する必要があることぐらいだろう。
https://coco-factory.jp/ugokuweb/move01/5-1-13/

最後に

やっぱり習うより慣れよの姿勢が大切なんだなと思う。何も実践を行わず知識のみ頭に打ち込んでいる人は、すぐに忘れてしまうし、必要な時に実践ができないから結局実践を多く行った人に負ける。ただ注意しなくてはならないのは、誰かがプログラミングは調べたら出てくるなんて言っていたけど、それはちょっと違う。今のプログラミング関連のサイト、特にweb関連のサイトは初学者寄りで理論を何も教えない。これを使えば出来るよ、なんていう気色の悪いサイトがおおい。大切なのは、実践の中で調べながら自分の知識をどんどん自由度の高いものにしていくこと。難しそうで詳しそうなサイトには、それだけ深い内容の詰まった英知が結集されているということだと思う。実際に僕はこのように記事にして自分の使いやすい形で知識を整理している。本ですら初学者を育ててくれないような物が多くなってしまった今、しっかりと戦えるエンジニアになるためには、難しいことに躊躇なく突っ込める挑戦者になるしか無いのだと思う。

Discussion