最終更新日:

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のみで作るドロップダウンメニューの解説

ポイント①:親リンク「a href=”#” class=”g-menu__link”」にpaddingを設定

ポイントのコード部分を一部抜粋しました。

          <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を必ず設定します。

ポイント②:親リスト「li class=”g-menu__item”」をpositionの起点にする(position: relative)

.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を無効にします。次で解説いたします。

ポイント③:親リスト「li class=”g-menu__item”」hoverイベント

.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秒かけて変化する設定をしています。

これで完成!

今回は以上となります!最後まで読んでいただきありがとうございました。

関連記事