ドロップダウンメニュー

次のようなCSSを書くとサンプルにマウスカーソルが乗ったときに要素の背景が黄色 に変わります。(但し、IEを除く)
※ 標準準拠モードのページであればIE7も動作します。
2007/09/03 IE7でスクリプトが動作しなくなっていました。(修正済)

<style type="text/css"><!--
span { padding: 2px; border: solid 2px #f00; }
span:hover { border-color: #00f; }
--></style>
<span>サンプル</span>
サンプル

つまり、正しくCSSの実装されたブラウザはa要素以外でも :hover 擬似クラスが 使えるということです。 これを利用すれば、CSSを工夫することによりドロップダウンメニューを組むことが 出来ますが、IEの欠陥はJavaScriptで補ってやる必要があります。

ドロップダウンメニュー縦向きのサンプルです。

※ サンプルのリンク先はありません。
※ マウスなどのポインティングデバイスを持たないシステムではご利用頂けません。

メニューはリスト要素を使ってマークアップします。 最上部のul要素のクラス名を dropdown としてください。 複雑になりがちですので、記述ミスには注意が必要ですね。

<ul class="dropdown">
 <li><a href="未設定">マジカル</a>
  <ul>
   <li><a href="未設定">妖しいページ</a></li>
   <li><a href="未設定">秘密のページ</a></li>
  </ul>
 </li>
 <li><a href="未設定">コミカル</a>
  <ul>
   <li><a href="未設定">アホなページ</a></li>
   <li><a href="未設定">ハイなページ</a></li>
   <li><a href="未設定">シャイなページ</a></li>
  </ul>
 </li>
 <li><a href="未設定">シリアス</a>
  <ul>
   <li><a href="未設定">ミステリー</a>
    <ul>
     <li><a href="未設定">邪悪なページ</a></li>
     <li><a href="未設定">幻のページ</a></li>
    </ul>
   </li>
   <li><a href="未設定">ファンタジー</a>
    <ul>
     <li><a href="未設定">未来のページ</a></li>
     <li><a href="未設定">夢のページ</a></li>
    </ul>
   </li>
  </ul>
 </li>
</ul>

縦向きのスタイルシートです。 作成したメニューにこれを読み込ませればIE以外は取り敢えず動作します。

.dropdown, .dropdown * {
 font-size: 12px;  /* 文字サイズ */
 line-height: normal;
 margin: 0;
 padding: 0;
}
.dropdown {
 border: solid 1px #000;  /* メインメニューのボーダー */
}
.dropdown, .dropdown ul, .dropdown li {
 width: 100px;  /* メニューの幅 */
}
.dropdown a {
 display: block;
 padding: 2px 0.5em;
}
.dropdown a, .dropdown a:link, .dropdown a:hover, .dropdown a:visited {
 color: #000;  /* 文字色 */
 text-decoration: none;
}
.dropdown a:hover {  /* マウスカーソルが乗ったとき */
 color: #00f;  /* 文字色 */
 background: #888;  /* 背景 */
}
.dropdown li {
 position: relative;
 display: block;
 list-style: none;
 background: #bbb;  /* メインメニュー背景 */
}
.dropdown li li {
 background: #ccc;  /* サブメニュー背景 */
}
.dropdown ul {
 visibility: hidden;
 position: absolute;
 left: 100px;  /* メニューの幅と同じ値 */
 top: -1px;  /* サブメニューのボーダー幅を減算 */
 border: solid 1px #000;  /* サブメニューのボーダー */
}
.dropdown li:hover > ul {
 visibility: visible;
}

スタイルシートは外部に置くことを想定していますが、ページ内に直接埋め込む場合は 勿論style要素 <style type="text/css"><!-- と --></style> で括ってヘッド内に置いてください。

そして、IEで動作させるためのスクリプトとバグを誤魔化すスタイルシートです。 IEの条件分岐コメントによりIE(バージョン5以上)は読みこむようにしています。
※ この条件分岐コメント内ではHTMLのコメントアウトは使用出来ません。

<!--[if IE]>
<style type="text/css">
.dropdown li { float: left; }
</style>
<script type="text/javascript">
window.attachEvent("onload",ddm_init);
function ddm_init() {
 var tn=document.getElementsByTagName("ul");
 for (var i=0; i < tn.length; i++)
  if (tn[i].className.match(/(^| )dropdown($| )/))
   tn[i].innerHTML=tn[i].innerHTML.replace(/(<li)/ig,
    '<li onmouseover="ddm_over(this);" onmouseout="ddm_out(this);"');
}
function ddm_over(elm) {
 if (elm.getElementsByTagName("ul")[0])
  elm.getElementsByTagName("ul")[0].style.visibility="visible";
}
function ddm_out(elm) {
 if (elm.getElementsByTagName("ul")[0])
  elm.getElementsByTagName("ul")[0].style.visibility="hidden";
}
</script>
<![endif]-->

このスクリプトを外部に置く場合はスクリプトの部分のみ(黒色の部分)を 新規作成したファイルに記述してください。 そして、次のように条件分岐コメントで括ってください。 (仮にファイル名は dropdown.js としています)
<!--[if IE]>
<style type="text/css"> .dropdown li { float: left; } </style>
<script type="text/javascript" src="dropdown.js"></script>
<![endif]-->
※ IEはバグのためかli要素の下端に謎の隙間が出来てしまうためli要素を全て float:left; にしています。

このスクリプトは、ページ内のクラス名dropdownのdl要素を見付け、その要素内の li要素にマウスが乗るとli要素直下のdl要素のスタイル visibilityをvisible(可視)、 マウスが離れたときにはhidden(不可視)に変わるようイベントハンドラを付け加えて います。このように簡単なスクリプトですが、ddm_over(this)としてli要素の イベントを拾っているのがポイントです。これを this を使わず関数 ddm_over()内で var elm=window.event.srcElement; とかやってしまうと li要素内のa要素にまでイベントが伝播してしまい酷い目に遭います。 (経験者談 orz )
※ IEはwindow.attachEventが複数使用されていると、要素に対するattachEventが 無効になり、setAttributeでのイベントハンドラが有効になるような妙な動作と なることがあるようでしたので、今回はreplaceでイベントハンドラを加えました。

こちらは横向きのサンプルです。横向きではメインメニュー全体( .dropdown )に ボーダー(枠)を付けるのはちょっと複雑なため枠無しとしました。 HTMLのマークアップ及びスクリプトは縦向きのサンプルと全く同じで、 スタイルシートに変更を加えただけのものです。


横向きのスタイルシートは次のようになります。

.dropdown, .dropdown * {
 font-size: 12px; /* 文字サイズ */
 line-height: normal;
 margin: 0;
 padding: 0;
}
.dropdown ul, .dropdown li {
 width: 100px;  /* メニューの幅 */
}
.dropdown a {
 display: block;
 padding: 2px 0.5em;
}
.dropdown a, .dropdown a:link, .dropdown a:hover, .dropdown a:visited {
 color: #000;  /* 文字色 */
 text-decoration: none;
}
.dropdown a:hover {  /* マウスカーソルが乗ったとき */
 color: #00f;  /* 文字色 */
 background: #888;  /* 背景 */
}
.dropdown li {
 position: relative;
 display: block;
 float: left;
 list-style: none;
 background: #bbb;  /* メインメニュー背景 */
}
.dropdown li li {
 background: #ccc;  /* サブメニュー背景 */
}
.dropdown ul {
 visibility: hidden;
 position: absolute;
 left: -1px;  /* サブメニューのボーダー幅を減算 */
 border: solid 1px #000;  /* サブメニューのボーダー */
}
.dropdown ul ul {
 left: 100px;  /* メニューの幅と同じ値 */
 top: -1px;  /* サブメニューのボーダー幅を減算 */
}
.dropdown li:hover > ul {
 visibility: visible;
}

※ 横向きは最上部のdl要素のサイズを指定しない事で、メインメニューのli要素を float:left; で横並びにしていますので、ドロップダウンメニューの次に置く要素には clear:left; のスタイルが必要になります。