[jQuery][CSS]ドロワーメニューを実装する

f:id:sotoogre:20200414022717p:plain

はじめに

毎回検索かけて調べているので忘備録として残しておきます。

SCSS、jQueryです。

普段はnode-sassを使用してsassファイルをcssに自動コンパイルさせています。こちらも記事にまとめておきたいところ。。

Drawer Menuを実装する

ドロワーメニューとは?というかたは以下のデモページからご覧ください。スマートフォンのサイトでよくみかける横からスライドで表示されるメニューのことです。

デモページ

まずはコードを載せておきます。

See the Pen humburger menu by soto-ogre (@soto-ogre) on CodePen.

色々なサイトを参考にしつつ、今後自分が使いやすいように多少の修正を加えてあります。

メディアクエリと組み合わせればレスポンシブも簡単に対応可能です。

以下、簡単な説明です。

5~6年ほど前にこのドロワーメニューを実装しようとした時、あらゆるサイトからコードをコピーしてきては全く理解ができず、修正したい部分が直せなかったり、直したら正しく動作しなかったりかなり四苦八苦した思い出があるので可能な限り丁寧に説明していこうと思います。(SCSS,jQueryの基礎知識がある程です。)

JS(jQuery)

jsの内容はとても単純。

function toggleNav() {
  var body = document.body; // bodyを取得
  var navBtn = $('.nav_btn')[0]; // メニューを開くボタンを取得 
  var blackBg = $('.nav_bg')[0]; // メニューオープン時に後ろの背景を暗くするための要素を取得 
  $(navBtn).on('click', function() { // 右上のボタンをクリックで 
    $(body).toggleClass('nav_open'); // <body>にメニューオープン時のクラスを付与
  });
  $(blackBg).on('click', function() { // body部分をクリックで
    $(body).removeClass('nav_open'); // 先ほど付与したクラスを削除
  });
}
toggleNav();

HTML

htmlもわりと単純です。

 <nav>
    <h1 id="sitetitle">MENU SAMPLE</h1>
    <ul id="nav">
      <li>
        <a href="">Home</a>
      </li>
      <li>
        <a href="">About</a>
      </li>
      <li>
        <a href="">Contents</a>
      </li>
      <li>
        <a href="">Contens</a>
      </li>
      <li>
        <a href="">Access</a>
      </li>
      <li>
        <a href="">Contact</a>
      </li>
    </ul>
    
    <div class="nav_btn" id="nav_btn">
      <span class="navBtn_line navBtn_line_1"></span>
      <span class="navBtn_line navBtn_line_2"></span>
      <span class="navBtn_line navBtn_line_3"></span>
    </div>
    <div class="nav_bg" id="nav_bg"></div>
  </nav>

非常にシンプルですね。 メニューの部分は<ul></ul>の部分。 class="nav_btn"の部分はメニューを開くためのボタン部分です。

class="nav_bg"はメニューが開いている間、メインコンテンツを暗くするために必要な要素です。

CSS

cssが少し複雑かも。でもひとつひとつ見ていけばわりとシンプルなことがわかるかと思います。

まずはul#navの部分。メニューの本体部分です。

#nav {
  transition: all .6s; // 表示(移動時)のアニメーションのプロパティ。0.6秒かけて表示される
  overflow-y: auto; // 要素の上下がはみ出た時の設定
  padding-top: 40px; // 開閉ボタン部分の余白を取る
  width: 300px; // 画面幅より小さく設定し、メイン画面をタップでメニューを閉じれるようにする
  height: 100vh; // 高さ:画面のheightに合わせる
  z-index: 200; // 他のコンテンツの上に来るように設定
  top: 0; // 
  right: -320px; // ボタンが押される前は画面から見えない位置に置く
  background-color: #fff;
  position: fixed; // スクロールしてもメニューが動かないように設定
}

お次は開閉ボタン部分。

こちらはボタン全体のスタイル。

.nav_btn {
  width: 44px; // 横幅
  height: 44px; // 縦幅
  z-index: 300; // メニューより上にくるように指定
  cursor: pointer; // カーソルで選択した時に矢印ではなくポインターになるように指定(これはなくても良いかもです)
  position: absolute; // 親要素(この場合はul#nav)のポジションを基準値に設定
  top: 7px; // 画面右上に固定
  right: 0px; // 画面右上に固定
}

こちらはボタンの線の指定。

ボタンの線は、小さな横長の箱に色を付けることで表現しています。

  .navBtn_line {
  transition: all .6s; // 0.6秒かけてアニメーションを動かす
  width: 28px; // 線の幅指定
  height: 2px; // 線の太さ指定
  right: 15px; // 線の位置を指定
  background-color: black;
  position: absolute; // 親要素(この場合は.nav_btn)のポジションを基準値に設定
  &_1 { top: 8px;} // 1番上の線の位置
  &_2 { top: 17px;} // 真ん中の線の位置
  &_3 { top: 26px;} // 下の線の位置
}

メニューが開いている間、メインコンテンツは半透明の黒色で覆われるようになっています。以下はメニューが閉じている間の設定です。

  .nav_bg {
    opacity: 0; // 透明度を0に。つまりは見えなくする。
    transition: all .6s; // 0.6秒かけて表示
    width: 100vw; // 画面横幅いっぱいに広げる
    height: 100vh; // 画面縦幅いっぱいに広げる
    z-index: 200; // メインコンテンツの上に被さるように設定
    top: 0; // 画面全体を覆うために左上を基準に要素を配置
    left: 0; // 同上
    visibility: hidden // 要素を隠す
    background-color: #000; // 背景色を黒に
    cursor: pointer; // ポインターカーソルにする
    position: fixed; // スクロールしても動かないようにする
  }

最後にメニューが開いている時の設定です。

.nav_open {
  nav #nav { right: 0; } // #navを表示する(位置を画面右から0のところに配置)

  .nav_bg {
    opacity: .5; // メインコンテンツを覆う部分の半透明度。
    visibility: visible; // 要素を可視にする
    z-index: 100; // メインコンテンツよりは上に、メニューよりは下にくるように数値を設定
  }
  
  .navBtn_line { // 開閉ボタンをバツマークに変形。
    &_1 {
      transform: rotate(45deg);// 線を45度回転させる
      top: 20px;
    }
    &_2 {
      width: 0; // 要素を不可視にするために横幅を0にする
      left: 50%; // メニューが閉じられた時に線が現れる最初の位置を指定
    }
    &_3 {
      transform: rotate(-45deg);// 線を-45度回転させる
      top: 20px;
    }
  }

おわりに

ひとつひとつ分解してみると意外と単純化かつシンプルだなあという印象です。

5~6年前は、こういうメニューを実装するためにライブラリを使用していたこともあるので単純さに驚きです。

グーグルなどで「ドロワーメニュー」や「ハンバーガーメニュー」と検索をかけると、タップでメニューが消せないもの、レスポンシブに対応しにくいもの、デザインが複雑に組まれすぎているものなどがわりとトップに来ていたりして使い勝手のいいものを見つけるのに毎度時間がかかってしまっていました。

今回、様々なサイトを参考にしつつ、コードをしっかりと読んだことで応用も効きそうです。

今回のコードはもちろんコピペでも使えますが、デザインは全くしていない状態なのでコード内容を理解してより目的にあったメニューを作りたいですね!