Milk+ea

Weblog Is My Hobby.

CSSとHTMLだけでメニューバーを作る

f:id:totora0155:20140829010212p:plain

See the Pen 2014-08-29 by nju33 (@nju33) on CodePen.

作り方

HTML

HTMLの構造はこうなっています。

<ul class="menu-">
  <li class="menu-case">
    <div class="menu-name">Menu 1</div>
    <ul class="menu-list">
      <li class="menu-one">Menu 1-1</li>
      <li class="menu-one">Menu 1-2</li>
      <li class="menu-one">Menu 1-3</li>
    </ul>
  </li>
  <li class="menu-case">-*-*- 略 -*-*-</li>
  <li class="menu-case">-*-*- 略 -*-*-</li>
  <li class="menu-case">-*-*- 略 -*-*-</li>
</ul>

.menu-caseを親要素としてその中に、親メニューの.menu-name、その次の要素に子メニューの.menu-listを配置・・・という構造になっています。

CSS

次にCSSの大事かなって箇所です。


ulはすべてリセットしちゃいます。

/* ulリセット */
.menu-, .menu-list {
  list-style: none;
  padding-left: 0;
  margin: 0;
}

.menu-casefloat: leftすることで横並びにします。

/* メニューを横並びに */
.menu-case {
  float: left;
}

floatで消えた高さを確保するために、.menu-caseの親要素にClearfixを使います。(overflowでは子メニューが表示できなくなるので駄目です)

.menu-:after {
  content: "";
  clear: both;
  display: block;
}

子メニューへposition: absoluteすることで、高さを.menu-name(親メニュー)だけにし、その場に絶対配置します。

z-index: -1bodyより後ろへ配置し隠します。
ついでにアニメーションで表示されるようにしたいので、opacity: 0で透明化させておきます。

また、そのままだと.menu-name分の幅になるのでwidthで好きな幅を設定します。

/* 子メニュー分の高さを除く */
.menu-list {
  position: absolute;
  opacity: 0;
  z-index: -1;
  width: 10em;
}

メニュー名にホバーした時に、次の要素である子メニューを表示させます。
.menu-name:hover + .menu-listとは、ホバーしている.menu-nameの次にある.menu-listという意味です。

z-index: 1によりbodyより手前に配置し、opacity: 1で見えるようにします。(実際にはtransitionでアニメーション化)

また、.menu-list:hoverにも同じように設定することで、子メニューへカーソルを移動させても隠れないようにしています。
marginなどを設定して、うっかり隙間を作っちゃうなんてことはしないように!

/* 子メニューを表示 */
.menu-name:hover + .menu-list, .menu-list:hover {
  opacity: 1;
  z-index: 1;
}

`親メニューや子メニューにホバーしているということは、もれなくその親要素にもホバーしているということになります。
下記により、子メニューが表示されている間は、親メニューの色を変更しています。

/* ホバー時、メニュー名の色変更 */
.menu-case:hover .menu-name {
  color: #507ea4;
}

要は、隙間ができないように子メニューを絶対配置すればいいだけなので、さらに子メニューから子子メニューなんかも簡単にできると思います。