CSSだけで実装する横並びのプルダウンメニュー

CSSだけで実装する横並びのプルダウンメニュー:css Tips11

前回は、読みやすい段組みレイアウトにつきまして、サンプルソースコードを交え記載いたしました。

column-countプルパティ使うことになれると、とても便利なことと思います。また、カラムを指定して区切り線なども表示できることから、実際にウェブサイトを作成する際、使用機会がとても多いことと思います。

今回は、CSSだけで実装する横並びのプルダウンメニューをについて記載してみようと思います。JavaScriptを使わなくても、CSSだけで作成できます。CSSに以前ご紹介したtransitionを指定することで、プルダウンする際のメニューにモーションを付けることができますので、JavaScriptで指定した際とほとんど挙動は同じような動きになります。

という事で、それでは今回はッ、

・プルダウンメニューのHTML
・メニューのデザインをCSSで作成
・プルダウンで動きを表現する

上記について記載していこうと思います…。

プルダウンメニューのHTML

まずは完成形を下記画像にてご紹介。

CSSだけで実装する横並びのプルダウンメニュー1
サンプルDemoページ

メニューオーバーで、サブメニューがプルダウンして表示されます。その際、transitionにてスルッとサブメニューが下に下がる表現を実装します。

サンプルHTML<ul id=”itemMenu”>
<li><a href=”#”>Menu1</a>
<ul class=”sub”>
<li><a href=”#”>Menu1_1</a></li>
<li><a href=”#”>Menu1_2</a></li>
<li><a href=”#”>Menu1_3</a></li>
<li><a href=”#”>Menu1_4</a></li>
<li><a href=”#”>Menu1_5</a></li>
</ul></li>
<li><a href=”#”>Menu2</a>
<ul class=”sub”>
<li><a href=”#”>Menu2_1</a></li>
<li><a href=”#”>Menu2_2</a></li>
<li><a href=”#”>Menu2_3</a></li>
<li><a href=”#”>Menu2_4</a></li>
</ul></li>
<li><a href=”#”>Menu3</a></li>
<li><a href=”#”>Menu4</a></li>
</ul>

Menu1とMenu2にサブメニューがulタグで入れ子になっている状態が、見てご理解いただけることとお思います。

メニューのデザインをCSSで作成

ますはプルダウンの見た目だけを先に作ります。子メニューとして降りてくる要素は現段階では邪魔になってしまうので、コメントアウトにして非表示にしておきます。親メニューの構成は、上記サンプルHTMLのようにul要素の子要素liが親メニューになり、さらにそのli要素の中に子要素になるul要素が記載されています。

ポイントは、ulにborderなどロールオーバー時に色を変えたい部分は設定しません。

liには、今回float:leftとメニューの横幅だけ指定しています。その子要素のaにスタイリングしていきます。
グラデーションとボーダーをロールオーバーで切り替える設定をしていきます。

サンプルCSS

ul#itemMenu li {
float:left;
width: 130px;
position:relative;
}
ul#itemMenu li a {
font-size: 12px;
color: #666;
text-decoration: none;
text-align:center;
padding: 0.9em 0;
display:block;
border-top:1px solid #AAA;
border-bottom:1px solid #AAA;
background-image:
linear-gradient(
rgb(255,255,255) 0%,
rgb(179,182,186) 70%,
rgb(169,173,184) 90%,
rgb(244,245,246) 100%);
background-color: #EEE;
text-shadow:0px 0px 0px rgba(255,255,255,0.2);
z-index: 100;
position:relative;
さらに上記CSSでは、aタグにボタンのスタイリングがしてあります。グラデーションの指定と上下にボーダーを指定しています。これがメニューボタンのアピアランスの基本になります。
CSSだけで実装する横並びのプルダウンメニュー2
次にメニューの左端と右端を角丸の形状にして、ボーダーを両端に付けたいので、:first-childと:last-childを領して設定します。
サンプルCSS

ul#itemMenu li:first-child a {
border-left:1px solid #AAA;
border-radius:6px 0 0 6px;
}
ul#itemMenu li:last-child a {
border-right:1px solid #AAA;
border-radius:6px 0 0 6px;
}

次に、プルダウンで降りてくる、子メニューのCSSを作製します。
上記に記載したコメントアウトを削除後、親要素のliメニューに作ったa要素のスタイリングが影響しますので、これらを上書きしていきます。

サンプルCSS

ul#itemMenu li ul.sub li {
float:none;
}
ul#itemMenu li ul.sub li a {
font-size: 12px;
color: #4c5482;
text-align:left;
padding: 0.9em 10px;
font-weight: normal;
background-image:none;
background-color: #FFF;
text-shadow:none;
border: none;
border-radius: 0;
}

さらに、子メニュー用のデザインをおこないます。降りてくるメニューがコンテンツの下に表示されないよう、上記サンプルCSSでul#itemMenu li aにpostitionとz-indexを指定してあります。

ul.sub(子メニュー)だけposition:absoluteで指定します。これはページのコンテンツに影響が出ないように、浮いた状態に指定したいためになります。

サンプルCSS

ul#itemMenu li {
– 省略 –
position:relative;
}
ul#itemMenu li a {
– 省略 –
z-index: 100;
position:relative;
}
– 省略 –
ul#itemMenu li ul.sub {
– 省略 –
position:absolute;
z-index: 10;
}

■メニューとコンテンツの位置関係
CSSだけで実装する横並びのプルダウンメニュー3

※position:absolute(絶対配置)での位置の指定は、基準点がどこになっているかを意識しておくことが重要です。

特に下準備をしていない場合はhtml要素が基準になります。この場合、今回のデザインのようにページを中央に配置するとウィンドウの横サイズの変動にメニューが付いていきません。
position:absoluteにしたい要素の親要素をpostion:relative(相対配置)を指定しておくと親要素を基準に位置が指定できるようになり、親要素の位置が別の要素の影響を受けて移動しても、それに連動するので非常に便利です。

次にメニューの下から子メニューが表示されたとき、子メニューの一部が親メニューの背面に食い込み、見えなくなってしまいます。これは、子メニューをposition:absoluteで設定るているためになります。top方向に、リストの高さ分の値を入れると解消されます。
サンプルCSS

ul#itemMenu li ul.sub {
– 省略 –
top: 30px;
– 省略 –
}

次にメニューの一番下の角丸も、子メニューのul要素で設定しておきます。あとは、ロールオーバーの色合いなどを調整します。これで見た目は問題ないことと思います。

サンプルCSS

ul#itemMenu li ul.sub {
position:absolute;
z-index: 10;
font-size: 10px;
top: 30px;
padding-top: 5px;
padding-bottom: 6px;
background: #FFF;
border-radius:0 0 6px 6px;
}
サンプルCSS

ul#itemMenu li ul.sub li a:hover {
background-image:none;
background-color: #a7b4fe;
border: none;
}

プルダウンで動きを表現する

まずは、通常時は子メニューが非表示の状態で、親メニューにロールオーバーすると子メニューが表示されるようにしてみます。
通常時のulにdisplay:noneを付けて、親が:hover状態のときにdisplay:blockにすれば、子メニューが表示される軽快な動きを表現できます。
サンプルCSS

ul#itemMenu li ul.sub {
display:none;
position:absolute;
z-index: 10;
font-size: 10px;
top: 30px;
padding-top: 5px;
padding-bottom: 6px;
background: #FFF;
border-radius:0 0 6px 6px;
}
ul#itemMenu li:hover ul.sub {
display: block;
}

次に、子メニューがプルダウンして表示される際のモーションをさらに追加してみます。ここでは、transition効果を使って、子メニューが少しゆっくりと降りてくる動きを表現します。
transitionは下記に以前記載した記事のリンクを記載しておきます。詳しくはご参照してください。

残念なことにtransitionでは、いくつか扱えるプロパティに制限があります。displayプロパティにはtransitionを使って動きを付けることができない為、上記で設定したul要素をdisplay:none→display:blockとして、ulの:hover時に子メニューを表示することができなくなります。

また、ここではメニュー項目の増減に柔軟に対応できる作りにしたいため、heightの値は固定した数値では指定ぜず、height:inheritとしています。transitionを使って、widthとheightのサイズを変更することはできるのですが、height:inheritのように数値を指定しない値ではtransitionが適用されません。

inheritは、親要素のプロパティ値をそのまま子要素に継承することを表す値です。inheritを使うことで、通常は親要素から継承しないプロパティの値を継承させることができます。
このためdisplay:none以外の方法で、ulの通常時に子メニューを隠しておくことにします。ここでは、opacityとmarginをtransitionに利用することにします。

また、通常時の子メニューを隠すために、widthとheightを0→:hover時にinheritへ切り替えを行うことにします。heightの値の調整は、今回の例だとtransitionには使えませんでしたが、表示・非表示の切り替えには利用できました。

サンプルCSS

ul#itemMenu li ul.sub {
height: 0;
width: 0;
overflow: hidden;
– 省略 –
top: 0;
– 省略 –
opacity: 0;
– 省略 –
}
transitionの値は、カンマ区切りで複数指定可能です。変更したいプロパティと、変化にかかる時間・加速度のつき方を設定してみます。
サンプルCSS

ul#itemMenu li ul.sub {
– 省略 –
transition: opacity 300ms linear, top 0.5s ease-in;
}

ここまでで完成になりますが、最後にソースコードをコピーして使えるようにまとめて記載してみます。

グローバルナビ:サンプルHTMLとCSS

<div class="wrapper" style="text-align:center; padding-top:100px;">
<div id="mainContent"><!--メイン-->
<ul id="itemMenu">
<li><a href="#">Menu1</a>
<ul class="sub">
<li><a href="#">Menu1_1</a></li>
<li><a href="#">Menu1_2</a></li>
<li><a href="#">Menu1_3</a></li>
<li><a href="#">Menu1_4</a></li>
<li><a href="#">Menu1_5</a></li>
</ul></li>
<li><a href="#">Menu2</a>
<ul class="sub">
<li><a href="#">Menu2_1</a></li>
<li><a href="#">Menu2_2</a></li>
<li><a href="#">Menu2_3</a></li>
<li><a href="#">Menu2_4</a></li>
</ul></li>
<li><a href="#">Menu3</a></li>
<li><a href="#">Menu4</a></li>
</ul>
</div><!--メイン-->
</div>
サンプルCSSbody {
background:#000;
margin: 0;
padding: 0;
font-size: 12px;
line-height: 1.4;
}
ul, li, dl, dt, dd {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
ul#itemMenu {
width: 600px;
margin: 0 auto;
font-weight:bold;
line-height: 1;
font-family: Tahoma, Geneva, sans-serif;
margin-bottom: 30px;
border-radius:6px;
/*textの影————————-*/
text-shadow:0px 0px 2px rgba(0,0,0,0.45);
/*boxの影————————-*/
box-shadow:1px 1px 3px rgba(0,0,0,0.4);
}
ul#itemMenu li {
float:left;
width: 130px;
position:relative;
}
ul#itemMenu:after {
content: “”;
display: block;
clear: both;
}
ul#itemMenu li a {
font-size: 12px;
color: #666;
text-decoration: none;
text-align:center;
padding: 0.9em 0;
display:block;
border-top:1px solid #AAA;
border-bottom:1px solid #AAA;
background-image:
linear-gradient(
rgb(255,255,255) 0%,
rgb(179,182,186) 70%,
rgb(169,173,184) 90%,
rgb(244,245,246) 100%);
background-color: #EEE;
text-shadow:0px 0px 0px rgba(255,255,255,0.2);
z-index: 100;
position:relative;
}
ul#itemMenu li a:hover {
background-image:
linear-gradient(
rgb(255,255,255) 0%,
rgb(169,176,215) 70%,
rgb(126,132,166) 90%,
rgb(255,255,255) 100%);
background-color: #a7b4fe;
border-top:1px solid #a7b4fe;
border-bottom:1px solid #a7b4fe;
}
ul#itemMenu li:first-child a {
border-left:1px solid #AAA;
border-radius:6px 0 0 6px;
}
ul#itemMenu li:last-child a {
border-right:1px solid #AAA;
border-radius: 0 6px 6px 0;
}
ul#itemMenu li:first-child a:hover {
border-left:1px solid #a7b4fe;
}
ul#itemMenu li:last-child a:hover {
border-right:1px solid #a7b4fe;
}
ul#itemMenu li ul.sub {
height: 0;
width: 0;
overflow:hidden;
position:absolute;
z-index: 10;
top: 5px;
font-size: 10px;
padding-top: 5px;
padding-bottom: 6px;
background: #FFF;
opacity: 0;
border-radius:0 0 6px 6px;
transition: opacity 300ms linear, top 0.5s ease-in;
}
ul#itemMenu li:hover ul.sub {
height: inherit;
width: inherit;
opacity: 1;
top: 30px;
}
ul#itemMenu li ul.sub li {
float:none;
}
ul#itemMenu li ul.sub li a {
font-size: 12px;
color: #4c5482;
text-align:left;
padding: 0.9em 10px;
font-weight: normal;
background-image:none;
background-color: #FFF;
text-shadow:none;
border: none;
border-radius: 0;
}
ul#itemMenu li ul.sub li a:hover {
background-image:none;
background-color: #a7b4fe;
border: none;
}

という事で今回は、CSSだけで実装する横並びのプルダウンメニューをサンプルコードを交え記載してみました。

CSS3のtransitionを使うことで、JavaScriptで実装したような動きを加えたプルダウンメニューの表現が出来たことと思います。JavaScriptに比べ、CSSで実装した場合は、動きもスムーズでまたページ自体の読み込みも速いというメリットもございます。

また、別記事に記載すると思いますが、今回記載したグローバルメニューとスマートフォン用のハンバーガーメニューをHTMLはワンソースで、CSSのメディアクエリを使用してレスポンシブに実装する方法もご紹介したいと思います。

とりあえず、今回はここまで…。

お仕事のご依頼は↓コチラより…、それではまた次回…。