HTMLとCSSでドロップダウンメニュー作成|レスポンシブ・子・孫メニューの作り方

man

困ってる人
メニューバーってどうやって作ればいいんだろう?
ナビゲーション?グローバルメニュー?
それでしたら今回は、一般的なメニューバーの配置方法やそこからのレスポンシブ対応までを簡単にご紹介しますね
operator

オペレーター

こんにちは、ヨロと申します。

今回作るのは、こんな感じのメニューバー。

今回はとても一般的な左上にロゴ、右上にハンバーガーボタン、

そして、それらの下にメニューボタンの一覧を並べて表示させるパターンのメニューバーの作り方の基本をご紹介。

HTMLとCSSでドロップダウンメニュー作成|レスポンシブ・子メニュー・孫メニューの作り方

という事で今回は、カーソルをメニューに合わせた時に、

別のカテゴリー(子要素)が表示されるようにしてみる。

HTML(index.html)

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/style.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
 
</head>
<body>
 
    <header>
        <div class="header-wrapper">

            <div class="title">
                <div class="logo">ロゴ</div>

                <div class="hamburger">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>        
            </div>


            <nav>
                <ul class="menus">
                    <li class="menu"><a href="#">ホーム</a></li>
                    <li class="menu"><a href="#">メニュー1</a></li>
                    <li class="menu"><a href="#">メニュー2</a>
                        <ul>
                            <li><a href="#">子メニュー1</a></li>
                            <li><a href="#">子メニュー2</a></li>
                            <li><a href="#">子メニュー3</a></li>
                        </ul>
                    </li>
                    <li class="menu"><a href="#">メニュー3</a></li>
                </ul>
            </nav>

        </div>
    </header>
 
    <script src="js/script.js"></script>
</body>
</html>  
 
// HTML(index.html)

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/style.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
 
</head>
<body>
 
    <header>
        <div class="header-wrapper">

            <div class="title">
                <div class="logo">ロゴ</div>

                <div class="hamburger">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>        
            </div>


            <nav>
                <ul class="menus">
                    <li class="menu"><a href="#">ホーム</a></li>
                    <li class="menu"><a href="#">メニュー1</a></li>
                    <li class="menu"><a href="#">メニュー2</a>
                        <ul>
                            <li><a href="#">子メニュー1</a></li>
                            <li><a href="#">子メニュー2</a></li>
                            <li><a href="#">子メニュー3</a></li>
                        </ul>
                    </li>
                    <li class="menu"><a href="#">メニュー3</a></li>
                </ul>
            </nav>

        </div>
    </header>
 
    <script src="js/script.js"></script>
</body>
</html>

そして次に、CSSで見た目の部分を整える、

CSS(style.css)

* { box-sizing: border-box; }
 
ul, li {
	padding: 0px;
	margin: 0px;
	list-style: none;
}


/* メニュー */
nav {
  background-color: greenyellow;
}

.menus {
	display: flex;
}
 
.menus li {
	list-style: none;
}
 
.menu a { /* 文字色 */
  display: block;
  padding: 15px;
	text-decoration: none;
}
 
.menu a:hover {
    background: rgba(128, 128, 128, 0.2); /* グレーの薄さ0.2 文字色はそのまま */
}
 
.menu ul {
  position: absolute;
  display: none;
	background-color: greenyellow; /* hover時に表示される子要素の色 */
	z-index: 10;
}
 
.menus li:hover ul {
	display: block; /* これがないと、hover時に表示されない */
}

そして、ロゴとハンバーガーボタンの部分に関してはこんな感じ。

// CSS(style.css) ロゴとハンバーガーボタン部分

.title {
  display: flex;
  height: 50px;
  padding: 0px 10px;
}

.title div:nth-child(1) {
  margin-right: auto;
}

.logo {
  margin: auto 0; /* ここで上下中央に配置 */
}

/* ここでハンバーガー枠全体のサイズ */
.hamburger {
  position: relative;
  width: 20px;
  height: 16px;
  margin: auto 0; /* ここで上下中央に配置 */
}
 
/* 三本線 */
.hamburger span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background-color: #000;
  z-index: 10;
}
 
/* 三本線の上の部分 */
.hamburger span:nth-of-type(1) {
    top: 0;
}
 
/* 三本線の中心部分 */
.hamburger span:nth-of-type(2) {
    top: 7px;
}
 
/* 三本線の下の部分 */
.hamburger span:nth-of-type(3) {
    bottom: 0;
}
 
 
/* ハンバーガー三本線:棒の動きや傾き加減など */
.hamburger,
.hamburger span {
  transition: all .3s; /* クリックしてからの動作時間 */
}
 
 
/* ここで数字を変えて傾きなどを調節 */
.hamburger.active span:nth-of-type(1) {
  transform: translateY(10px) rotate(-45deg);
  -webkit-transform: translateY(7px) rotate(-45deg);
}
.hamburger.active span:nth-of-type(2) {
  opacity: 0;
}
.hamburger.active span:nth-of-type(3) {
  transform: translateY(-12px) rotate(45deg);
  -webkit-transform: translateY(-7px) rotate(45deg);
}

script.js

そして、ハンバーガーボタンがきちんと反応してくれるようにするには、

script.js:ハンバーガーボタンを動かす

$(function() {
    $('.hamburger').click(function(){
        $('.hamburger').toggleClass('active');
    });
});

と書いて終わり。

これらのような、メニューの階層が少ないものだと、HTMLCSSの記述も比較的シンプルで短く簡単。

ただ、もう少し階層の深いメニューボタンを作りたいといった場合は、

ヘッダー部分の中身を、もう少し細かく書いていく必要が出てくる。

ドロップダウンメニューの作成:階層が深い場合、子メニュー、孫メニューの作り方

深い階層のメニューバーというのは、こんな感じで、

通常のメニューに加え、子メニュー、孫メニュー、下手すると孫メニューまでもあるパターン。

今回は、これを試しに作っていく。

HTML(index.html)

<header>
    <div class="header-wrapper">

        <div class="title">
            <div class="logo">ロゴ</div>

            <div class="hamburger">
                <span></span>
                <span></span>
                <span></span>
            </div>        
        </div>

        <nav>
	        <ul class="menu">
	            <li><a href="#">HOME</a></li>
	            <li><a href="#">メニュー1</i></a>
	                <ul>
	                    <li><a href="#">子メニュー</a></li>
	                    <li><a href="#">子メニュー</a></li>
	                    <li><a href="#">子メニュー</a></li>
	                </ul>
	            </li>

	            <li><a href="#">メニュー2</a>
	                <ul>
	                    <li><a href="#">子メニュー</a></li>
	                    <li><a href="#">子メニュー <i class="fas fa-angle-double-right"></i></a>
	                        <ul>
	                            <li><a href="#">孫メニュー</a></li>
	                            <li><a href="#">孫メニュー</a></li>
	                        </ul>
	                    </li>
	                    <li><a href="#">子メニュー</a></li>
	                    <li><a href="#">子メニュー <i class="fas fa-angle-double-right"></i></a>
	                        <ul>
	                            <li><a href="#">孫メニュー</a></li>
	                            <li><a href="#">孫メニュー</a></li>
	                        </ul>
	                    </li>
	                </ul>
	            </li>

	            <li><a href="#">メニュー3</a>
	                <ul>
	                    <li><a href="#">子メニュー</a></li>
	                    <li><a href="#">子メニュー <i class="fas fa-angle-double-right"></i></a>
	                        <ul>
	                            <li><a href="#">孫メニュー</a></li>
	                            <li><a href="#">孫メニュー <i class="fas fa-angle-double-right"></i></a>
	                                <ul>
	                                    <li><a href="#">ひ孫メニュー</a></li>
	                                    <li><a href="#">ひ孫メニュー</a></li>
	                                    <li><a href="#">ひ孫メニュー</a></li>
	                                </ul>
	                            </li>
	                        </ul>
	                    </li>
	                </ul>
	            </li>
	        </ul>
        </nav>

    </div>
</header>

CSSの処理をせずに、HTMLだけだとこんな感じ。

そして、次にCSS

CSS(style.css)

* { box-sizing: border-box; }
 
a {
	text-decoration: none;
}

ul, li {
	padding: 0px;
	margin: 0px;
	list-style: none;
}


.title {
    display: flex;
    height: 50px;
    padding: 0px 10px;
}
  
.title div:nth-child(1) { /* ここでハンバーガーボタンを指定 */
    margin-right: auto;
}
  
  .logo {
    margin: auto 0; /* ここで上下中央に配置 */
}


/* ハンバーガーボタン:ここで全体のサイズ */
.hamburger {
    position: relative;
    width: 20px;
    height: 16px;
    top: 10px;
    left: 10px;
}
  
/* 三本線 */
.hamburger span {
    position: absolute;
    left: 0;
    width: 100%;
    height: 2px;
    background-color: #000;
    z-index: 10;
}

/* 三本線の上の部分 */
.hamburger span:nth-of-type(1) {
    top: 0;
}

/* 三本線の中心部分 */
.hamburger span:nth-of-type(2) {
    top: 7px;
}

/* 三本線の下の部分 */
.hamburger span:nth-of-type(3) {
    bottom: 0;
}
  
  
/* ハンバーガー三本線:棒の動きや傾き加減など */
.hamburger,
.hamburger span {
    display: inline-block;
    transition: all .4s; /* クリックしてからの動作時間 */
}
  
  
/* ここで数字を変えて傾きなどを調節 */
.hamburger.active span:nth-of-type(1) { /* 上の棒線 */
    transform: translateY(10px) rotate(-45deg);
    -webkit-transform: translateY(7px) rotate(-45deg);
}

.hamburger.active span:nth-of-type(2) { /* クリックしたら消える真ん中の棒線 */
    opacity: 0;
}

.hamburger.active span:nth-of-type(3) { /* 下の棒線 */
    transform: translateY(-12px) rotate(45deg);
    -webkit-transform: translateY(-7px) rotate(45deg);
}


/* メニューの一覧 */
ul.menu {
    background-color: greenyellow;
    letter-spacing: -100px; /* inline-blockで要素を横並びにした時の隙間を無くす */
}
 
/* メイン */
ul.menu li {
    position: relative;
    display: inline-block; /* これが無いと、子と孫の位置がかなりずれる */
    letter-spacing: normal; /* 上で指定したletter-spacingを元通りに */
}

ul.menu a {
    display: block; /* リンクボタン全体をクリック出来るように */
    padding: 15px; /* ここでメニューのサイズ */
}

ul.menu a:hover {
    background: rgba(128, 128, 128, 0.2); /* グレーの薄さ0.2 文字色はそのまま */
}
 
/* サブメニュー(hover時) */
ul.menu li:hover > ul {
    display: block; /* ここで表示(hover時) */
}
 
/* サブメニュー */
ul.menu ul {
    display: none;
    position: absolute;
}
 
/* サブメニュー以降 */
ul.menu ul li {
    width: 160px; /* ここである程度の長さを指定しないと、文字が縦並びになる(px指定) */
    background-color: greenyellow;
}
 
/* 孫メニュー以降の表示について */
ul.menu ul ul {
    display: none;
    position: absolute;
    top: -1px; /* これがないと、項目の子メニューの真横に孫メニューが表示されない */
    left: 100%; /* 親要素から、左から右に100%ずらす */
}

.fa-angle-double-right { /* Font Awesomeのアイコン */
    font-size: 10px;
}

今回、>> の矢印アイコン部分には「Font Awesome」というサービスを使っていて、

Font Awesomeを読み込んで使う時のタグは、head内で、

<link href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet">

を読み込ませればOK。

あとは、好みのアイコンを、Font Awesomeのサイトから探してくる。

ここまで書ければ、PC表示に関しては問題なし。

ドロップダウン メニューバー:レスポンシブ(スマートフォン)対応

PCで閲覧時は、ハンバーガーボタンを見えないようにして、メニューの一覧表示をする設定に、

スマホ表示時は、ハンバーガーボタンを表示し、メニューの一覧を隠す設定に。

スマートフォン仕様(レスポンシブ対応)にする場合は、CSSを再度別のファイルで読み込む、

今回はスマホで見た場合の設定を、responsive.cssに書いていくとして、

ファイルを読み込むタグは、

<link rel="stylesheet" href="css/responsive.css">

という事でまずは、ハンバーガーボタンを消す設定に、

style.css(PC閲覧時)

/* style.css:ハンバーガーボタンを隠す */

.hamburger,
.hamburger span {
    /* ここに */
}

display: none; を追加して、ハンバーガーボタンを見えないようにする。

そして、スマホ側では、

responsive.css(レスポンシブ)

/* responsive.cssではハンバーガーボタンが見えるように */

.hamburger,
.hamburger span {
    /* ここに追加 */
}

display: inline-block; を追加して、ハンバーガーボタンを表示する設定に。

ドロワーメニューで、メニュー一覧を表示する設定

今回はスマホで見る場合は、メニュー画面を画面の外に配置しておいて、

ハンバーガーボタンをクリックしたと同時に、メニューの一覧が画面上に表示される(画面の中に入ってくる)ように設定を書いてみる。

という事で、簡単なドロワーを作成。その場合まずは、

/* ここでメニューの一覧を画面の外へ配置 */
nav {
    transform: translateX(100%);
}

transform: translateの意味合い

// transform: translate();

transform: translateX(100%); → 指定した要素を画面の右側に追いやる
transform: translateX(-100%); → 指定した要素を画面の左側に追いやる
transform: translateY(100%); → 指定した要素を画面の下に追いやる
transform: translateY(-100%); → 指定した要素を画面の上に追いやる

数字を指定する際は、%だけじゃなくvhなどを使用してもOK。

今回は、ハンバーガーボタンをクリックする度に、メニューの一覧が右側から現れるようにする設定。

script.jsに、

$(‘nav’).toggleClass(‘active’);を追加し、.hamburgerをクリックする度に、

navにも、activeというクラスをつけたり消したりといった指示を出す。

// script.jsでtoggleClassを使ってactiveクラスを足したり外したり

$(function() {
    $('.hamburger').click(function(){
        $('.hamburger').toggleClass('active');
        $('nav').toggleClass('active');
    });
});

.toggleClassを使う事によって、ボタンをクリックする度にその要素に「active」というクラス名を付与する事が出来る。

そして次に、CSS部分。

script.jsで、要素をクリックをする度に、.activeというクラスをつけたり外したりする設定を書いたので、

responsive.css内の要素に、activeクラスがついた時の処理を書く、

/* navにactiveクラスがついた時は、画面外にあるメニュー一覧を、元の位置に戻すように指示 */

nav.active {
    transform: translateX(0%);
}

そうする事によって、ボタンをクリックする度に、ドロワーの開閉が出来るようになる。

ただ、今のままではクリックしてからメニューの一覧が、元の位置に戻るまでが早過ぎるので、

transition: all .3s; を付け加えて。アニメーションの速度の調節をする。

responsive.css

nav {
    transform: translateX(100%); /* ここで要素を画面外に配置 */
    transition: all .3s; /* 0.3秒かけて */
}

nav.active { /* アクティブ時 */
    transform: translateX(0%); /* ここで要素を元の位置に */
    transition: all .3s; /* 0.3秒かけて */
}

これでOK。

メニューバーの見た目の部分をレスポンシブ仕様(スマートフォン対応)に

今の状態だと、まだメニュー部分が横並びになっているので、

これらを縦並びにして見た目を軽く整える。その場合は、

responsive.css

ul.menu li {
    display: inline-block;
}

の、display: inline-block;の部分を display: initial;で初期値に戻す。

ul.menu ul {
    display: none;
    position: absolute;
}

の中身も同じように、initialに、

ul.menu ul ul {
    display: none;
    position: absolute;
    top: -1px;
    left: 100%;
}

の中身も全て同じように、initialに、

そうすれば、全ての項目が縦並びになる、

あとの細かい調整は、またCSSで整えていけばOK。

そして最終的なソースコードはこんな感じ。

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="css/style.css">
    <link rel="stylesheet" href="css/responsive.css">
    <link href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
 
</head>
<body>
 
    <header>
        <div class="header-wrapper">
    
            <div class="title">
                <div class="logo">ロゴ</div>
    
                <div class="hamburger">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>        
            </div>
    
            <nav>
                <ul class="menu">
                    <li><a href="#">HOME</a></li>
                    <li><a href="#">メニュー1</i></a>
                        <ul>
                            <li><a href="#">子メニュー</a></li>
                            <li><a href="#">子メニュー</a></li>
                            <li><a href="#">子メニュー</a></li>
                        </ul>
                    </li>
    
                    <li><a href="#">メニュー2</a>
                        <ul>
                            <li><a href="#">子メニュー</a></li>
                            <li><a href="#">子メニュー <i class="fas fa-angle-double-right"></i></a>
                                <ul>
                                    <li><a href="#">孫メニュー</a></li>
                                    <li><a href="#">孫メニュー</a></li>
                                </ul>
                            </li>
                            <li><a href="#">子メニュー</a></li>
                            <li><a href="#">子メニュー <i class="fas fa-angle-double-right"></i></a>
                                <ul>
                                    <li><a href="#">孫メニュー</a></li>
                                    <li><a href="#">孫メニュー</a></li>
                                </ul>
                            </li>
                        </ul>
                    </li>
    
                    <li><a href="#">メニュー3</a>
                        <ul>
                            <li><a href="#">子メニュー</a></li>
                            <li><a href="#">子メニュー <i class="fas fa-angle-double-right"></i></a>
                                <ul>
                                    <li><a href="#">孫メニュー</a></li>
                                    <li><a href="#">孫メニュー <i class="fas fa-angle-double-right"></i></a>
                                        <ul>
                                            <li><a href="#">ひ孫メニュー</a></li>
                                            <li><a href="#">ひ孫メニュー</a></li>
                                            <li><a href="#">ひ孫メニュー</a></li>
                                        </ul>
                                    </li>
                                </ul>
                            </li>
                        </ul>
                    </li>
                </ul>
            </nav>
    
        </div>
    </header>
 
    <script src="js/script.js"></script>
</body>
</html>

style.css

* { box-sizing: border-box; }
 
a {
	text-decoration: none;
}

ul, li {
	padding: 0px;
	margin: 0px;
	list-style: none;
}


.title {
    display: flex;
    height: 50px;
    padding: 0px 10px;
}
  
.title div:nth-child(1) { /* ハンバーガーボタンを指定 */
    margin-right: auto;
}
  
  .logo {
    margin: auto 0; /* ここで上下中央に配置 */
}


/* ハンバーガーボタン:ここで全体のサイズ */
.hamburger {
    position: relative;
    width: 20px;
    height: 16px;
    top: 10px;
    left: 10px;
}
  
/* 三本線 */
.hamburger span {
    position: absolute;
    left: 0;
    width: 100%;
    height: 2px;
    background-color: #000;
}

/* 三本線の上の部分 */
.hamburger span:nth-of-type(1) {
    top: 0;
}

/* 三本線の中心部分 */
.hamburger span:nth-of-type(2) {
    top: 7px;
}

/* 三本線の下の部分 */
.hamburger span:nth-of-type(3) {
    bottom: 0;
}
  
  
/* ハンバーガー三本線:棒の動きや傾き加減など */
.hamburger,
.hamburger span {
    display: inline-block;
    transition: all .4s; /* クリックしてからの動作時間 */
    z-index: 10;
}
  
  
/* ここで数字を変えて傾きなどを調節 */
.hamburger.active span:nth-of-type(1) { /* 上の棒線 */
    transform: translateY(10px) rotate(-45deg);
    -webkit-transform: translateY(7px) rotate(-45deg);
}

.hamburger.active span:nth-of-type(2) { /* クリックしたら消える真ん中の棒線 */
    opacity: 0;
}

.hamburger.active span:nth-of-type(3) { /* 下の棒線 */
    transform: translateY(-12px) rotate(45deg);
    -webkit-transform: translateY(-7px) rotate(45deg);
}


/* メニューの一覧 */
ul.menu {
    background-color: greenyellow;
    letter-spacing: -100px; /* inline-blockで要素を横並びにした時の隙間を無くす */
}
 
/* メイン */
ul.menu li {
    position: relative;
    display: inline-block; /* これが無いと、子と孫の位置がかなりずれる */
    letter-spacing: normal; /* 上で指定したletter-spacingを元通りに */
}

ul.menu a {
    display: block; /* リンクボタン全体をクリック出来るように */
    padding: 15px; /* ここでメニューのサイズ */
}

ul.menu a:hover {
    background: rgba(128, 128, 128, 0.2); /* グレーの薄さ0.2 文字色はそのまま */
}
 
/* サブメニュー(hover時) */
ul.menu li:hover > ul {
    display: block; /* ここで表示(hover時) */
}
 
/* サブメニュー */
ul.menu ul {
    display: none;
    position: absolute;
}
 
/* サブメニュー以降 */
ul.menu ul li {
    width: 160px; /* ここである程度の長さを指定しないと、文字が縦並びになる(px指定) */
    background-color: greenyellow;
}
 
/* 孫メニュー以降の表示について */
ul.menu ul ul {
    display: none;
    position: absolute;
    top: -1px; /* これがないと、項目の子メニューの真横に孫メニューが表示されない */
    left: 100%; /* 親要素から、左から右に100%ずらす */
}

.fa-angle-double-right { /* Font Awesomeのアイコン */
    font-size: 10px;
}

responsive.css

@media (max-width: 1000px) {

.hamburger,
.hamburger span {
    display: inline-block;
}

header {
    position: relative;
}

/* メニュー部分 */
nav {
    position: absolute;
    top: 0;
    width: 100vw;
    transform: translateX(100%);
    transition: all .3s;
}

/* メニュー部分:アクティブ時 */
nav.active {
    transform: translateX(0%);
    transition: all .3s;
}

nav {
    transform: translateX(100%); /* ここで要素を画面外に配置 */
    transition: all .3s;
}

nav.active { /* アクティブ時 */
    transform: translateX(0%); /* ここで要素を元の位置に */
    transition: all .3s;
}

ul.menu li {
    display: initial;
}

ul.menu ul {
    display: initial;
    position: initial;
}

ul.menu ul ul {
    display: initial;
    position: initial;
    top: initial;
    left: initial;
}

}  

・script.js
 
// script.js

$(function() {
    $('.hamburger').click(function(){
        $('.hamburger').toggleClass('active');
        $('nav').toggleClass('active');
    });
});

終わり。