CSSのみで横並びのプルダウンメニューを作る
今回は「CSSのみで実装する横並びのプルダウンメニュー」を作ってみたいと思います。横並びのメニュー親のliの中にマウスホバーで子のliを表示します。特別な動きをつけずに簡単に作るものと、transitionをつかってプルダウンに動きをつけたものを作ってみたいと思います。下にデモも用意していますので、どんなものかご覧ください。
CONTENTS
- 1.基本的なHTML
- 2.CSSでメニューのデザインを整える
- 3.positionで表示位置を調整
- 4.displayプロパティでホバー時に表示
- 5.transitionでプルダウンに動きをつける
- 6.transition解説
1.基本的なHTML
基本的なHTMLは簡単です。ulのリストの中にサブメニューとなるulを入れ子にしました。ここでいうとMenuのliが親でsubMenuが子ですね。
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 |
<ul class="Menu"> <li><a href="#">Menu1</a> <ul class="subMenu"> <li><a href="#">subMenu1</a></li> <li><a href="#">subMenu2</a></li> <li><a href="#">subMenu3</a></li> <li><a href="#">subMenu4</a></li> </ul> </li> <li><a href="#">Menu2</a> <ul class="subMenu"> <li><a href="#">subMenu1</a></li> <li><a href="#">subMenu2</a></li> <li><a href="#">subMenu3</a></li> <li><a href="#">subMenu4</a></li> <li><a href="#">subMenu5</a></li> </ul> </li> <li><a href="#">Menu3</a> <ul class="subMenu"> <li><a href="#">subMenu1</a></li> <li><a href="#">subMenu2</a></li> <li><a href="#">subMenu3</a></li> <li><a href="#">subMenu4</a></li> <li><a href="#">subMenu5</a></li> </ul> </li> <li><a href="#">Menu4</a> </li> <li><a href="#">Menu5</a> </li> </ul> |
2.CSSでメニューのデザインを整える
CSSでデザインを簡単に整えておきます。ここは自分の好きなように設定されてください。一応今回使用したCSSをのせておきます。(全体通してCSSが大雑把なのはお許しください。)親背景のメニューを薄いグレーにして右側にborder:1px、そして一番右端のborderはli:last-childで消しています。子メニューは親要素のスタイルが継承されているので、不要なスタイルを上書きします。子メニューの背景は濃いグレーで同様に下にborderをつけ、同じく一番下はli:last-childで消しています。
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 |
.container{ max-width:1000px; margin:0 auto; } .Menu{ width:100%; margin-top:30px; } ul,li{ list-style:none; margin:0; padding:0; } .Menu li{ float:left; width:199px; } .Menu li a{ background:#ccc; border-right:1px solid #8c8c8c; text-align:center; font-size:14px; display:block; padding:10px 0; text-decoration:none; color:#fff; } .Menu li:last-child a{ border-right:none; } .Menu li ul.subMenu li a{ float:none; background:#8c8c8c; border-right:none; border-bottom:1px solid #ccc; display:block; } .Menu li ul.subMenu li:last-child a{ border:none; } |
3.positionで表示位置を調整
メニューの下にくる要素でサブメニューが隠れてしまわないようにさきほどのメニューにpositionとz-indexを指定します。親となるli要素(.Menu li)にposition:relativeを指定してpositionの親要素とします。.Menu li aにはposition:relativeとz-indexを使用します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
.Menu li{ float:left; width:199px; position:relative;/* ここで親要素を指定 */ } .Menu li a{ background:#ccc; border-right:1px solid #8c8c8c; text-align:center; font-size:14px; display:block; text-decoration:none; color:#fff; padding:10px 0; position:relative;/* z-index用のpositionプロパティ */ z-index:100;/* z-indexで前面に表示 */ } |
次に子要素subMenuにposition:absoluteを指定します。さきほどrelativeで親要素を指定しているので、subMenuはMenuを親となります。absoluteは絶対位置なので指定した親要素が基準になります。なにも指定がない場合はhtmlを基準とします。今の状態だと親要素にsubMenuがかぶってしまうので、absoluteのtopで親メニュー分の高さを調整してください。そして、メニュー後続の要素の下にこの子メニューがもぐりこんで見えなくならないようにz-indexも指定しておきます。後々のtransitionで動きをつける場合に子メニューが親メニューの下からでてるようにしたいので、子メニューの値を親メニューより小さくしてください。
1 2 3 4 5 |
.Menu li ul.subMenu{ position:absolute; z-index:10; top:39px; } |
4.displayプロパティでホバー時に表示
subMenuは通常は見えずにマウスホバーした状態で表示するようにしたいので、普段はdisplay:noneで非表示にしておいて、マウスホバー時に表示するようにします。
1 2 3 4 5 6 |
.Menu li ul.subMenu{ position:absolute; z-index:10; top:39px; display:none;/* ここを追加(普段は非表示になる) */ } |
そしてホバー時に表示するコードを追加します。
1 2 3 |
.Menu li:hover ul.subMenu{ display:block; } |
DEMO
ここまでの流れでプルダウンメニューは実装できました。とくに動きをつける必要がないのであれば、ここまでできれば充分だと思います。次はこのメニューに動きをつけてみたいと思います。
5.transitionでプルダウンに動きをつける
まず、さきほど作ったdisplay:noneとblockで表示と非表示を切り替えていましたが、このdisplayプロパティはtransitionでは使えません。なので子メニューでopacityを使い、隠します。そして、ホバー時に表示させるようにしようと思います。さきほどのMenu li ul.subMenuで追加したdisplay:none;とMenu li:hover ul.subMenuのdisplay:blockは削除してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.Menu li ul.subMenu{ position:absolute; z-index:10; top:0; opacity:0;/*opacity:0(透過)で非表示にしておく*/ width:0;/*widthとheightを0に*/ height:0; transition: opacity 400ms linear, top 400ms ease-in;/*動きをつけるtransition(後述)*/ } .Menu li:hover ul.subMenu{ opacity: 1;/*opacityを1(透過なし)にして表示*/ top: 30px; width:inherit;/*inheritでもとの値を継承*/ height:inherit; } |
DEMO
これでマウスホバーした時にサブメニューがゆっくりと表示するような動きになったのではないでしょうか?linearは一定の速度でease-inは最初はゆっくりでだんだん早くなります。
inherit(継承)
ひとつポイントですが、subMenu(通常時)のwidthとheightに0を指定して、ホバー時にinheritを指定していますが、これはopacityで透過にしてしまうと、子メニューの要素は透過になっているだけで実際には親メニューの下に要素は存在します。ということは見えない子メニューに反応してしまって親メニューのボタンをホバーせず、実際に存在する子メニューをホバーするとプルダウンが開いてしまいます。通常時はwidthとheightを0にしておくことでそれを防ぐことができます。ホバー時のinheritは通常継承しない親要素のプロパティでも強制的に継承することができます。よって一度0にした高さと幅を継承し、ホバー時に表示させます。
6.transition解説
transitionは要素が変化していくプロパティです。ここでは簡単に解説しておきますが、transitionにはtransition-property(どう変化させるかの設定。今回の場合だとopacityとtop(position)、transition-duration(変化にかかる時間、単位はs(秒)ms(ミリ秒))、transition-timing-function(変化する具合の調整)、transition-delay(変化が始まるタイミングs、ms指定)これらの動きをまとめてtransitionでまとめて指定することができます。今回の例だとopacityがtransition-property、400msはtransition-duration、linearがtransition-timing-functionになります。transition-delayは使用しておりません。今回の例で個人的にちょっとわかりずらかった部分transition-propertyを解説すると、下記のように最初に指定しているtransition-propertyはどういう変化をつけるかを指定します。opacity以外にもbackground(背景)の変更やボーダー(border)だったり、幅(width)だったり、なんでもいいので変化させたいプロパティを記述します。そして次の動きで変化後の値を入力します。
1 2 3 4 5 6 7 8 9 10 11 |
.Menu li ul.subMenu{ overflow:hidden;/*はみでた部分がホバーで反応してしまうので隠す*/ top:0;/*始めは表示しないのでopacityとも0に*/ opacity:0; transition: opacity 400ms linear, top 400ms ease-in;/*プロパティはopacityとtopをここで指定*/ } .Menu li:hover ul.subMenu{ opacity: 1;/*ホバー時に表示するように値を設定*/ top: 39px; } |
動きの参考やプロパティは「フラップイズムさん」のブログが参考になりました。以上になります。まだ試したことない方はホームページも様になるので、一度試してみてください。
参考書籍:CSS3デザインブック 仕事で絶対に使うプロのテクニック
追記2018.2.5
この記事の改訂版として新たに「CSSのみで多階層のプルダウンメニューを作る【改訂版】」を書きました。この記事の内容にプラス多階層のメニューをつけたものです。