前回、javascriptで縦並びのアコーディオンメニューの実装方法についてまとめました。↓
今回は横並びのアコーディオンメニューを実装方法についてまとめたいと思います。
仕上がりはこんな感じになります。
HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>グローバルメニュー</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <header> <h1>header</h1> <nav> <div class="menu"> <li id="menu1" class="target">1 <ul id="menuopen1" class="close"> <li>1-1</li> <li>1-2</li> <li>1-3</li> </ul> </li> </div> <div class="menu"> <li id="menu2" class="target">2 <ul id="menuopen2" class="close"> <li>2-1</li> <li>2-2</li> <li>2-3</li> </ul> </li> </div> <div class="menu"> <li id="menu3" class="target">3 <ul id="menuopen3" class="close"> <li>3-1</li> <li>3-2</li> <li>3-3</li> </ul> </li> </div> <div class="menu"> <li id="menu4" class="target">4 <ul id="menuopen4" class="close"> <li>4-1</li> <li>4-2</li> <li>4-3</li> </ul> </li> </div> <div class="menu"> <li id="menu5" class="target">5 <ul id="menuopen5" class="close"> <li>5-1</li> <li>5-2</li> <li>5-3</li> </ul> </li> </div> </nav> </header> <wrapper> <main> <a href="#"><div class="mainflex"> <img src="#"> <p>ああああああああああああああああああああああああああああああああああああああああああああああああああ</p> </div></a> <a href="#"><div class="mainflex"> <img src="#"> <p>ああああああああああああああああああああああああああああああああああああああああああああああああああ</p> </div></a> <a href="#"><div class="mainflex"> <img src="#"> <p>ああああああああああああああああああああああああああああああああああああああああああああああああああ</p> </div> </a> <a href="#"><div class="mainflex"> <img src="#"> <p>ああああああああああああああああああああああああああああああああああああああああああああああああああ</p> </div> </a> <a href="#"><div class="mainflex"> <img src="#"> <p>ああああああああああああああああああああああああああああああああああああああああああああああああああ</p> </div> </a> <a href="#"><div class="mainflex"> <img src="#"> <p>ああああああああああああああああああああああああああああああああああああああああああああああああああ</p> </div> </a> </main> <side> <div class="sidebox"><a href="#"><div class="sideimg"><img src="#"></div> <p>ああああああああああああああああああああああああああああああああああああああああああああああああああ</p></a></div> <div class="sidebox"><a href="#"><div class="sideimg"><img src="#"></div> <p>ああああああああああああああああああああああああああああああああああああああああああああああああああ</p></a></div> <div class="sidebox"><a href="#"><div class="sideimg"><img src="#"></div> <p>ああああああああああああああああああああああああああああああああああああああああああああああああああ</p></a></div> </side> </wrapper> <footer> <p>footer</p> </footer> <script src="js/main.js"></script> </body> </html> |
header内のnavタグ要素が今回のアコーディオンメニューの記述になります。
<li id>をjavascriptのイベントトリガーとします。ここのクリックで、子要素のulを表示、非表示させます。
css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
body { margin: 0; padding: 0; } p { margin: 0; } header { background: pink; padding: 10px; margin-bottom: 3px; } header h1 { margin: 0; } nav { display: flex; } .menu { width: 20%; } .target { position: relative; cursor: pointer; } nav ul { margin: 0; padding: 0; position: absolute; width: 100%; max-height: 0; overflow: hidden; transition: 0.5s; } nav li { list-style: none; background: pink; text-align: center; cursor: pointer; } .open { max-height: 100vh; } img { width: 100px; height: 100px; } main { background: orange; padding: 10px; margin-bottom: 3px; } .mainflex { display: flex; padding: 10px 0; } main p { padding-left: 10px; } side { display: block; background: green; padding: 10px; margin-bottom: 3px; } .sideimg { text-align: center; } footer { background: skyblue; padding: 10px; font-size: 20px; text-align: center; } @media screen and (min-width:600px) { body { max-width: 1000px; } main { width: 70%; } side { width: 30%; margin-left: 3px; } .sidebox { padding-top: 30px; } wrapper { display: flex; } } |
イベントトリガーのli要素をposition relativeとし、子要素のulをabsoluteとします。(li要素には文字列が入っているため、abusoluteはrelativeに内包されず下方に配置されます。)
一見positionのプロパティはいらないように思いますが、これをしないと要素が浮かないので、メニュー開閉の際に親要素も広がってしまいます。
あとはul要素のmax-heightを0にして、メニューを隠しておきます。同時にoverflow:hiddenで文字列も消しておきます。
javascriptで開閉のアクションをさせるので、開く用のcssを.openで作成しています。
max-heightとvhを使用しているのは、何故か通常のheightと%指定だとtransitionが効かない為です。
javascript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
"use strict"; { const menu1 = document.getElementById("menu1"); const menu2 = document.getElementById("menu2"); const menu3 = document.getElementById("menu3"); const menu4 = document.getElementById("menu4"); const menu5 = document.getElementById("menu5"); const menuopen1 = document.getElementById("menuopen1"); const menuopen2 = document.getElementById("menuopen2"); const menuopen3 = document.getElementById("menuopen3"); const menuopen4 = document.getElementById("menuopen4"); const menuopen5 = document.getElementById("menuopen5"); menu1.addEventListener("click", () => { menuopen1.classList.toggle("open"); }); menu2.addEventListener("click", () => { menuopen2.classList.toggle("open"); }); menu3.addEventListener("click", () => { menuopen3.classList.toggle("open"); }); menu4.addEventListener("click", () => { menuopen4.classList.toggle("open"); }); menu5.addEventListener("click", () => { menuopen5.classList.toggle("open"); }); } |
あとはjavascriptでイベント処理をさせるだけです。
liにidを振っているので、それをクリックすればul要素にopenのクラスが追加されるので、メニューが開きます。
また、toggle動作になるので、再度クリックすれば閉じるといった挙動になります。
今回は一応簡易的なレスポンシブに対応させていますが、双方で同じメニューが出るようにしています。
スマホ時はハンバーガーメニューにしたい場合は、冒頭にある過去記事にてまとめていますので、是非参考にしてください。