ドロワーメニューの仕組みを理解するために、コードを徹底解剖してみた

コード
スポンサーリンク

こんにちは朱夏です。

今回は、ドロワーメニューの仕組みにを理解するために、コードを分解して調べてみたいと思います。

朱夏
朱夏

独自のデザインにしたい。

表示位置や色を変更するにはどうしたらいいんだろう?

 

 

仕組みを理解すれば、どこをいじれば何が変わるのか解りますよ。

それではいってみましょう。

 

[もくじ]

コード紹介
部品ごとに解説
*メインページ本体*
*メニューボタン*
*メニュー一覧*
*本体カバー*

動きの解説
あとがき

 

コード紹介

初めにコードを紹介します。
前回紹介したドロワーメニューのコードを使います。

※前回も紹介しましたが、このコードはこちらのサイトで紹介されていたものをアレンジして作成しております。

 

■THML

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width,initial-scale=1"> 
        <title>モバイルTOP</title>
        <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
        <link rel="stylesheet" href="style2.css">
        <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
        <script src="https://kit.fontawesome.com/da0fa6be04.js" crossorigin="anonymous"></script>

        <!--[if lt IE 9]>
        <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <script src="http://css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js"></script>
        <![endif]-->
        <script src="js/script.js"></script>
    </head>
    <body>
        <!----- ヘッダー ----->
        <header>
            <div id="nav-drawer" class="bg-success py-2 px-3 text-right">
                <!-- チェックボックス -->
                <input id="nav-input" type="checkbox" class="nav-unshown">
                <!-- メニューボタンのアイコン -->
                <label id="nav-open" for="nav-input"><i class="fas fa-bars"></i></label>
                <!-- 本体カバー -->
                <label id="nav-close" for="nav-input"></label>
                <!-- メニュー -->
                <div id="nav-content">
                    <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">Top</a></div>
                    <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">HTML</a></div>
                    <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">JavaScript</a></div>
                    <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">PHP</a></div>
                </div>
            </div>
        </header>
        <!----- ヘッダー END ----->
    </body>
</html>

 

■CSS

#nav-drawer {
    /* ポジション指定 */
    position: relative;
}


.nav-unshown {
    /* 存在を消す */
    display:none;
}

/*アイコンのスペース*/
#nav-open {
    display: inline-block;
    width: 30px;
    height: 22px;
    vertical-align: middle;
}

/*閉じる用の薄黒カバー*/
#nav-close {
    display: none;/*はじめは隠しておく*/
    position: fixed;
    z-index: 99;
    top: 0;/*全体に広がるように*/
    left: 0;
    width: 100%;
    height: 100%;
    background: black;
    opacity: 0;
    transition: .3s ease-in-out;
}

/*中身*/
#nav-content {
    overflow: auto;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 9999;/*最前面に*/
    width: 80vw;/*左側に隙間を作る(閉じるカバーを表示)*/
    height: 100vh;
    background: #fff;/*背景色*/
    transition: .3s ease-in-out;/*滑らかに表示*/
    -webkit-transform: translateX(100vw);
    transform: translateX(100vw);/*右に隠しておく*/
}

/*チェックが入ったらもろもろ表示*/
#nav-input:checked ~ #nav-close {
    display: block;/*カバーを表示*/
    opacity: .5;
}

#nav-input:checked ~ #nav-content {
    -webkit-transform: translateX(20vw);
    transform: translateX(20vw);/*中身を表示(右からスライド)*/
    box-shadow: 6px 0 25px rgba(0,0,0,.15);
}

.mobile-nav {
    list-style: none;
}

.mobile-nav {
    text-decoration: none;
}

.mobile-nav:hover {
    background-color: rgb(231, 231, 231);
}

 

 

 

部品ごとに解説

それでは解剖開始です。
最初にパーツを分けていきます。

使用しているパーツは以下の4つです。

  • メインページ本体
  • メニューボタン
  • メニュー一覧
  • 本体カバー

 

それぞれについて詳しく調べていきます。

 

メインページ本体

メインコンテンツが表示されているエリアです。
ここのどこかにメニューボタンを設置する場所を決めます。

ページ四隅のどこかに設置しるのが一般的かと思います。
今回の例では右上に設置しています。

ベースとなる部分なので特にポイントなどはありません。

メニューボタン

恐らく今回の重要ポイントとなるメニューボタンです。

押すたびにON、OFFが切り替わるスイッチとしての機能が欲しいので、チェックボックスを採用しています。

コードとしてはこの部分です。

<input id="nav-input" type="checkbox" class="nav-unshown">
<label id="nav-open" for="nav-input"><i class="fas fa-bars"></i></label>

 

適用しているスタイルはこちら。

#nav-drawer {
    /* ポジション指定 */
    position: relative;
}


.nav-unshown {
    /* 存在を消す */
    display:none;
}

/*アイコンのスペース*/
#nav-open {
    display: inline-block;
    width: 30px;
    height: 22px;
    vertical-align: middle;
}

 

ポイントとしては、display:none;でチェックボックスそのものの表示を消している事です。
実際に動作させるボタンをlabelタグで紐付けています。
labelタグのfor属性に、チェックボックスに付けたidを指定することで、そのlabelはチェックボックスをクリックしたときと同じ動作をする様になります。

なぜこんな大変なことをしているかというと、チェックボックスの見た目を変更したいからです。
チェックボックスのまま使用する事も可能ではありますが、やはりデザイン的には微妙かと思います(^_^;)

あと、チェックボックスは小さいので押しにくいというのもありますね。

 

■メニューボタンのポイントまとめ

  • チェックボックスでON/OFFスイッチ
  • チェックボックス自体は隠す
  • labelタグで見た目を変更

 

メニュー一覧

ボタンを押したときに現れるメニューになります。

基本的なメニューしか表示させていませんが、画像やボタンなど、普通のHTMLのページとしてデザインする事が可能です。

コードとしてはこの部分になります。

<div id="nav-content">
    <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">Top</a></div>
    <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">HTML</a></div>
    <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">JavaScript</a></div>
    <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">PHP</a></div>
</div>

 

適用されているスタイルはこちら。

#nav-content {
    overflow: auto;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 9999;/*最前面に*/
    width: 80vw;/*左側に隙間を作る(閉じるカバーを表示)*/
    height: 100vh;
    background: #fff;/*背景色*/
    transition: .3s ease-in-out;/*滑らかに表示*/
    -webkit-transform: translateX(100vw);
    transform: translateX(100vw);/*右に隠しておく*/
}

 

ポイントとなるのは「position: fixed;」です。
「position」プロパティでは、要素の位置をどうやって指定するかを決める事が出来ます。
「fixed」という値は、その要素の位置(ポジション)を絶対位置で指定し、更にスクロールしても動かない様に画面に固定します。

次に注目するのが、「z-index: 9999;」です。
これはwebページを表示する時の「重なる順番」を指定していて、数字が大きいほど上に重なります。
ボタンを押したときにメニューが最前面に表示されていないと、他の要素でメニューが隠れてしまう事があるので、それの防止策ですね。
z-indexの概念は理解しにくいものですが、Photoshopなどを触ったことがある人だとレイヤーをイメージすると解りやすいかもしれません。
数字が大きいほど上のレイヤーです。

transform: translateX(100vw);」では、メニュー一覧の初期位置を設定しています。
メニュー一覧の左上を起点に、X軸の位置を100vwずらしています。
vwは、画面の横幅を指定するもので、一番左を0vw、一番左を100vwとして指定できます。
なので、メニュー一覧はちょうど右側の画面外で待機している状態になっています。

後の部分はコメントアウトにも書かれている様に、メニュー一覧の見た目を決めています。
あとは登場する時の秒数なんかも指定しています。

 

■メニュー一覧のポイントまとめはこちら。

  • 最前面に表示
  • 画面外で待機
  • 表示位置は固定

 

本体カバー

本体カバーとは、メニューが表示されたときに余白となる部分にかけるカバーの事です。
カバーをかける理由は主に2つあります。

  1. メニュー以外の部分を隠す
  2. メニューを閉じるボタンの役割

ドロワーメニューの場合、表示されたメニューを閉じるためには、メニュー以外の余白をクリック(タップ)するのが一般的です。
この本体カバーにはその機能がついています。

コードはこの部分になります。

<label id="nav-close" for="nav-input"></label>

 

適用しているスタイルはこちら。

#nav-close {
    display: none;/*はじめは隠しておく*/
    position: fixed;
    z-index: 99;
    top: 0;/*全体に広がるように*/
    left: 0;
    width: 100%;
    height: 100%;
    background: black;
    opacity: 0;
    transition: .3s ease-in-out;
}

 

ポイントは「display: none;」で表示を消している部分です。
displayプロパティでnoneの値を指定した場合、表示だけでなく存在そのものを消す事が出来ます。
どういうことかというと、その要素が持っている機能や配置などが無視された状態になるのです。
今回の例で言うと、画面表示だけなら「opacity: 0;」で非表示になっています。
しかし、この「display: none;」を指定していなかった場合、画面をクリック(タップ)する度にメニューが出たり引っ込んだりを繰り返すようになってしまいます。

もう一つのポイントとしては、「z-index: 99;」でページ本体より上、メニュー一覧より下に重ねている事です。
メニュー一覧より上にすると、メニューをクリック(タップ)した時にメニューが閉じてしまうのでそれを防ぐためです。

そして、本体カバーも「position: fixed;」で固定しています。
メニューを開いた時にカバーの表示がずれてしまったら、メニューが閉じられなくなってしまいます。
それを防ぐためにも、固定は必須ですね。

後の部分は実際の見た目に関わる部分ですが、メニューが表示されたときに表示するための基準値として指定しています。
「background: black;」や「opacity: 0;」はそのための準備ですね。

 

■本体カバーのポイントまとめはこちら。

  • 存在を消しておく
  • 閉じるボタン機能
  • 本体より上、メニューより下

 


各パーツについて分解してみました。
次の項で、どうやって動いているかを細かく見ていきたいと思います。

 

動きの解説

最初に、おおまかな動きについて説明していきます。
イメージとしては以下の様な動きをしています。

 

 

メニューボタンを押したら、メニュー一覧が画面外からニュッと出てきて、ページ本体は暗くなる。
そして暗くなったページ本体をクリック(タップ)すると、メニュー一覧が引っ込む。

こんな動きをしています。

動作のポイントとなるのは、やはりチェックボックスの部分です。
注目する部分はidとclassです。

というわけでもう一度HTMLのコードです。

<div id="nav-drawer" class="bg-success py-2 px-3 text-right">
    <!-- チェックボックス -->
    <input id="nav-input" type="checkbox" class="nav-unshown">
    <!-- メニューボタンのアイコン -->
    <label id="nav-open" for="nav-input"><i class="fas fa-bars"></i></label>
    <!-- 本体カバー -->
    <label id="nav-close" for="nav-input"></label>
    <!-- メニュー -->
    <div id="nav-content">
        <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">Top</a></div>
        <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">HTML</a></div>
        <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">JavaScript</a></div>
        <div class="mobile-nav border-bottom py-2 px-4"><a class="text-secondary" href="#">PHP</a></div>
    </div>
</div>

 

メニューの部分だけ切り出しました。
そして、動作時のCSSがこちらです。

#nav-input:checked ~ #nav-close {
    display: block;/*カバーを表示*/
    opacity: .5;
}

#nav-input:checked ~ #nav-content {
    -webkit-transform: translateX(20vw);
    transform: translateX(20vw);/*中身を表示(右からスライド)*/
    box-shadow: 6px 0 25px rgba(0,0,0,.15);
}

 

ポイントの1つ目は「#nav-input:checked」です。
ここはチェックボックスがONになっている場合を示す疑似セレクタになります。

ポイントの2つ目は“~”(チルダ)です。
CSSのセレクタでチルダが意味するのは、「同じ階層にある」という意味です。
なので、1行目を翻訳すると以下になります。

文:#nav-input:checked ~ #nav-close
訳:id「#nav-input」がチェックONの時、同じ階層にある「#nav-close」

 

これにより、チェックONの時の「#nav-close」と「#nav-content」のスタイルを書くことが出来る様になりました。

あとは表示されたときのスタイルを指定するだけです。

 

そこでポイントの3つ目、「#nav-input:checked ~ #nav-close」に指定する「display: block;」です。
これを忘れると、本体カバーが出てきません。
そしてメニューを閉じることができなくなります(;・∀・)

 

■動作のポイントまとめ

  • checkedはチェックONの疑似要素
  • チルダは同じ階層を指定
  • 本体カバーの「display: block;」は必須

 

あとがき

というわけで、ドロワーメニューを分解して仕組みを見てきました。
ここまで中身を理解できていれば、どこをいじったら自分の考えたデザインを反映させることが出来るのか解って来ると思います。

今回のまとめはこちら。

  • メニュー一覧は画面外に隠す
  • メニューボタンは実はチェックボックス
  • 疑似セレクタcheckedでチェックON時のスタイルを指定

 

今回の学習のアウトプットとして、ちょっとメニュー一覧の表示アニメーションをいじったものを作ってみました。

See the Pen
jOPGeLx
by 朱夏 (@syunatsu1)
on CodePen.

 

変化が解りにくいかもですが、メニューの表示がスライドではなく回転して出てくるようにしました。

今回はここまでです。
次回もよろしくお願いします。

 

タイトルとURLをコピーしました