CSSでドロップダウンメニュー
ドロップダウンメニューのようなダイナミックな動作はJavaScriptが得意としますが、CSSだけでも実装可能です。
JavaScriptを使用せず、CSSのみでドロップダウンメニューを作成するポイントは以下の3つ。
- postionプロパティ、displayプロパティを駆使する
- ダイナミック擬似クラスhoverを使用する
- 子セレクタを使用する
問題はIE6では、hoverはa要素しか適用範囲でないこと、さらに子セレクタも適用されないということです。
ie7-jsという、IE6でもa要素以外にも:hoverが使えたり子セレクタが使用できるスクリプトがあるので、それを利用することで代用が利きます。
今回はie7-jsを使用せず、どこまでできるかやってみたいと思います。
子孫セレクタを応用すると、IE6でも子セレクタと同様の動作するので、そちらのテクニックを使用します。以下のページを参考にしてください。
hoverはダイナミックな動きですので、やはりJavaScriptを使用しなければなりません。簡単なのは、IEの独自拡張であるexpression() 関数を使用します。これはCSS内でJavaScriptコードを読み込めるものです。ただし、CSSの仕様にないものですので、ソースコードはinvalidになってしまいます。
完成サンプルは以下のとおりです。
サンプル
※ページの中にサンプルを記述しているため、ブラウザによっては正常に動作しない場合があります。ご了承ください。サンプルはWindows XPのIE6、Firefox3.5、Safari4.0.3、Opera9.64 、Chrome2.0で動作確認済みです。
基本のHTMLソースは以下のとおりです。メインメニューと3つのサブメニューを用意しました。
(X)HTMLコード
<div id="menu">
<ul>
<li><a href="#">menu1</a>
<ul>
<li><a href="#">submenu1</a></li>
<li><a href="#">submenu2</a></li>
<li><a href="#">submenu3</a>
<ul>
<li><a href="#">submenu3-1</a></li>
<li><a href="#">submenu3-2</a></li>
<li><a href="#">submenu3-3</a>
<ul>
<li><a href="#">submenu3-3-1</a></li>
<li><a href="#">submenu3-3-2</a></li>
<li><a href="#">submenu3-3-3</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><a href="#">menu2</a>
<ul>
<li><a href="#">submenu4</a></li>
<li><a href="#">submenu5</a></li>
</ul>
</li>
<li><a href="#">menu3</a>
<ul>
<li><a href="#">submenu6</a></li>
<li><a href="#">submenu7</a></li>
<li><a href="#">submenu8</a></li>
<li><a href="#">submenu9</a></li>
</ul>
</li>
</ul>
</div>
最低限必要なCSSソースコードです。
CSSコード
/* メインメニュー */
#menu ul {
display:block;
list-style-type: none;
margin:0;
padding:0;
}
/* サブメニュー1段目 */
#menu ul ul{
display:none;
position:absolute;
top:100%;
left:0;
}
/* サブメニュー2段目以降 */
#menu ul ul ul {
top:0;
left:100%;
}
/* リスト */
#menu li {
float:left;
}
#menu li li {
clear:both;
}
#menu li:hover {
position:relative;
}
#menu li:hover > ul {
display: block
}
/* IE6用 */
* html #menu li {
behavior: expression(
this.onmouseover=new Function("this.className='column1'"),
this.onmouseout=new Function("this.className=''"),
this.style.behavior = 'none'
);
}
* html #menu li li {
behavior: expression(
this.onmouseover=new Function("this.className='column2'"),
this.onmouseout=new Function("this.className=''"),
this.style.behavior = 'none'
);
}
* html #menu li li li {
behavior: expression(
this.onmouseover=new Function("this.className='column3'"),
this.onmouseout=new Function("this.className=''"),
this.style.behavior = 'none'
);
}
#menu .column1 {position:relative;}
#menu .column1 ul {display:block;}
#menu .column1 * ul {display:none;}
#menu .column2 {position:relative;}
#menu .column2 ul {display:block;}
#menu .column2 * ul {display:none;}
#menu .column3 {position:relative;}
#menu .column3 ul {display:block;}
#menu .column3 * ul {display:none;}
後半部分がIE6用のソースコードになります。
hoverの代わりにJavaScriptのonmouseoverイベントハンドラを使用しています。サブカテゴリの数だけliの入れ子の指定が必要です。
本来なら、「* html li」の指定だけでドロップダウンできるはずなのですが、その入れ子の「* html li li」、さらにその入れ子の「* html li li li」と指定が必要となります。
例えばメインのメニューのli要素にマウスが載ったときに.column1のスタイルが実行されるのですが、onmouseoverの適用範囲が表示されたサブメニューまで及びます。
サブメニューのサブメニューを表示したくても、onmouseoverのままなので、新しくonmouseoverイベントハンドラを呼び出す必要があります。そのため、サブメニューの数分expression()関数が必要になってしまいます。
もっとよい書き方があるのかもしれませんが、あまりJavaScriptに詳しくないので、これが私にとっての最善の書き方になります。
これだけでは味気ないのでデザインしていきます。ここでは簡単に背景と余白を体裁します。
CSSコード
/* デザイン */
#menu li {
line-height:1.6em;
text-align: center;
background:#ddd;
}
#menu li li {
text-align: left;
}
#menu li a{
display: block;
width:100px;
text-decoration:none;
color:#333;
padding:0 10px;
}
#menu li:hover {
background:#7BBA10;
color:#333;
}
#menu .column1, #menu .column2, #menu .column3 {
color:#333;
background:#7BBA10;
}
この例のようにwidthとpaddingを同時に指定する場合は、HTMLファイルが「完全標準モード」になるようにDOCTYPE宣言を指定する必要があります。
例えば、XHTMLファイルなら、
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
などです。
ドロップダウンメニューはJavaScriptで実装したほうがよりリッチに
以上、CSSのみでドロップダウンメニューを作成しましたが、やはりJavaScriptのほうがよりスムーズで美しいドロップダウンメニューができるので、そちらがお勧めではあります。
参考までに素敵なJavaScriptで実装する素敵なドロップダウンメニューはこちら。
jQuery ドロップダウンメニュー | CSS Lecture

