最終更新日:
cssのみ!ドロップダウンメニューの作り方
hoverしたら現れるドロップダウンメニューを作っていきます。
目次
実際のコードとデモ
まずは実際のコードを載せます。
<header class="header">
<div class="header__inner">
<div class="header__row">
<div class="header__logo">
<img src="https://placehold.jp/cfcfcf/ffffff/200x100.png?text=%E3%83%AD%E3%82%B4" alt="">
</div>
<div class="header__menu">
<ul class="g-menu">
<li class="g-menu__item">
<a href="#" class="g-menu__link">HOME</a>
</li>
<li class="g-menu__item">
<a href="#" class="g-menu__link">親ページ1</a>
<ul class="g-menu__dropdown-menu">
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ1</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ2</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ3</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ4</a>
</li>
</ul>
</li>
<li class="g-menu__item">
<a href="#" class="g-menu__link">親ページ2</a>
<ul class="g-menu__dropdown-menu">
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ2の子ページ1</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ2の子ページ2</a>
</li>
</ul>
</li>
<li class="g-menu__item">
<a href="#" class="g-menu__link">親ページ3</a>
<ul class="g-menu__dropdown-menu">
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ3の子ページ1</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ3の子ページ2</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ3の子ページ3</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ3の子ページ4</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ3の子ページ5</a>
</li>
</ul>
</li>
<li class="g-menu__item">
<a href="#" class="g-menu__link">親ページ4</a>
<ul class="g-menu__dropdown-menu">
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ4の子ページ1</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ4の子ページ2</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ4の子ページ3</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ4の子ページ4</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ4の子ページ5</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ4の子ページ6</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ4の子ページ7</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</header>
/* リセット */
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
a {
text-decoration: none;
color: inherit;
}
/* ベース設定 */
body {
height: 1000000px;
}
/* レイアウト */
.header {
position: fixed;
top: 0;
left: 0;
z-index: 999999;
width: 100%;
background: #fff;
box-shadow: 0 0 10px rgba(0,0,0,0.5);
}
.header__inner {
width: 95%;
max-width: 1100px;
margin-left: auto;
margin-right: auto;
}
.header__logo img {
width: 200px;
height: auto;
}
.header__row {
display: flex;
align-items: center;
justify-content: space-between;
}
.header__menu {
padding-left: 15px;
}
/* メイン部分 */
.g-menu {
display: flex;
}
.g-menu__item {
position: relative;
}
.g-menu__link {
display: block;/* ポイント!! */
padding: 50px 20px;/* ポイント!! */
font-size: 16px;
line-height: 1.5;
color: #000;
}
.g-menu__dropdown-menu {
opacity: 0;/* ポイント!! */
pointer-events: none;/* ポイント!! */
position: absolute;
top: 100%;/* ポイント!! */
left: 0;
background: #f2f2f2;
width: 200%;
}
.g-menu__dropdown-menu-item {
border-bottom: 1px solid #ccc;
}
.g-menu__dropdown-menu-item:last-child {
border-width: 0;
}
.g-menu__dropdown-menu-link {
display: block;
padding: 10px;
font-size: 14px;
line-height: 1.5;
}
.g-menu__item:hover .g-menu__link {
color: red;
transition: .5s;
}
.g-menu__item:hover .g-menu__dropdown-menu {
opacity: 1;
pointer-events: auto;
transition: .5s;
}
.g-menu__dropdown-menu-link:hover {
background: skyblue;
}
注: /* メイン部分 */ より上の部分はレイアウトなどの設定です。この部分について今回は触れません。
注:デモページ閲覧はPC推奨
cssのみで作るドロップダウンメニューの解説
ポイントのコード部分を一部抜粋しました。
<li class="g-menu__item">
<a href="#" class="g-menu__link">親ページ1</a>
<ul class="g-menu__dropdown-menu">
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ1</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ2</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ3</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ4</a>
</li>
</ul>
</li>
.g-menu__link {
display: block;/* ポイント!! */
padding: 50px 20px;/* ポイント!! */
font-size: 16px;
line-height: 1.5;
color: #000;
}
ここに上下paddingを設定し、ヘッダーの高さ分クリック領域を増やしておきます。
その際、aタグはインライン要素なのでdisplay: blockを必ず設定します。
.g-menu__item {
position: relative;
}
.g-menu__dropdown-menu {
opacity: 0;/* ポイント!! */
pointer-events: none;/* ポイント!! */
position: absolute;
top: 100%;/* ポイント!! */
left: 0;
background: #f2f2f2;
width: 200%;
}
一見、親リンク「a class=”g-menu__link”」を起点(position: relative)にすると思ってしまいますが、ここを起点にすると、その下のドロップダウンメニュー「ul class=”g-menu__dropdown-menu”」位置が正しく設定できません。
その下のドロップダウンメニュー「ul class=”g-menu__dropdown-menu”」は、親リンク「a class=”g-menu__link”」の外にあるからです。
一方、親リスト「li class=”g-menu__item”」はドロップダウンメニュー「ul class=”g-menu__dropdown-menu”」を含んでいます。なのでここにposition: relativeを設定。
ドロップダウンメニュー「ul class=”g-menu__dropdown-menu”」には、position: absoluteを設定。top: 100%を設定すれば、起点(position: relative)の一番下にくっつけることができます。
また、ドロップダウンメニュー「ul class=”g-menu__dropdown-menu”」にopacity: 0を設定して見えなくします。後ほどこれをopacity: 1にします。
その際、pointer-events: noneを設定しないと、(見えていないが)ドロップダウンメニューがいるであろう部分にマウスを当てたとき、ドロップダウンメニューが現れてしまいます。
この理由は、親リスト「li class=”g-menu__item”」のhoverでドロップダウンメニューの表示を制御しており、親リストがドロップダウンメニューも含んでいるからです。
<li class="g-menu__item">
<a href="#" class="g-menu__link">親ページ1</a>
<ul class="g-menu__dropdown-menu">
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ1</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ2</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ3</a>
</li>
<li class="g-menu__dropdown-menu-item">
<a href="#" class="g-menu__dropdown-menu-link">親ページ1の子ページ4</a>
</li>
</ul>
</li>
htmlを見ると、ドロップダウンメニュー「ul class=”g-menu__dropdown-menu”」が、親リスト「li class=”g-menu__item”」の中に入っています。
そして、ドロップダウンメニューがhoverされるということは、それを含んでいる親リスト「li class=”g-menu__item”」がhoverされたということになるということです。
この問題の対策として、pointer-events: noneを設定します。
pointer-events: noneは、「マウス操作を無効にする」というcssプロパティです。
pointer-events: noneを指定すると、指定された要素はクリック、hoverなどマウスに関連する動作が一才無効になります。
つまり、pointer-events: noneを設定したドロップダウンメニュー「ul class=”g-menu__dropdown-menu”」は、hoverしても何も起こらないということになり、現れることはありません。
なお、親リスト「li class=”g-menu__item”」hover時に、pointer-events: noneを無効にします。次で解説いたします。
.g-menu__item:hover .g-menu__dropdown-menu {
opacity: 1;
pointer-events: auto;
transition: .5s;
}
:hoverを指定するのは親リンクの「a href=”#” class=”g-menu__link”」ではありません。
全てを含んでいる親リスト「li class=”g-menu__item”」に:hoverを指定します。
そして、:hoverした時のドロップダウンメニュー「ul class=”g-menu__dropdown-menu”」のopacity: 1、pointer-events: auto(pointer-events: noneの無効化)にしてそれぞれ無効化します。
また、transitionでは変化する時間を指定しています。この場合、hoverした後0.5秒かけて変化する設定をしています。
これで完成!
今回は以上となります!最後まで読んでいただきありがとうございました。