このサイト(HTML版)のプルダウンメニューの作成をCSS3のみで実現してみました。
まず、HTMLの構造から ■HTML
ul、liの入れ子で階層を作っていきます。 最初のul(id=menu)をトップ階層とし、メインメニューはliで横並びにします。 次の階層のul,liがサブメニューになります。
■CSS gradientで背景をグラデーション、border-radiusで枠を角丸に [css]
display: inline-block;
margin: 15px 0 0 0;
padding: 5px 0 0 0;
line-height: 100%;
font-size: 14px;
background: -moz-linear-gradient(top, #406b9f, #588ab5);
background: -webkit-gradient(linear, left top, left bottom, from(#406b9f), to(#588ab5));
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
} [/css] text-shadowでリンクテキストに影をつける
[css]
display: block;
margin: 0;
padding: 8px 20px;
color: #eeeeee;
text-decoration: none;
text-shadow: 5px 5px 5px rgba(0, 0, 0, 1.0);
}
color: #ff2222;
text-shadow: 2px 2px 2px rgba(0, 0, 0, 1.0);
} [/css]
▽第1階層 トップメニューはliを横並び [css]
position: relative;
float: left;
margin: 0 5px;
padding: 0 0 5px;
list-style: none;
} [/css]
liをロールオーバーした時に色を変更 [css]
background: -moz-linear-gradient(top, #406b9f, #588ab5);
background: -webkit-gradient(linear, left top, left bottom, from(#406b9f), to(#588ab5));
} [/css]
▽第2階層 ここがポイントで、第2階層にあたるulをvisibility=hiddenで予め隠しておく。 Fadeアニメーションするために、opacity=0と設定する。 [css]
visibility: hidden;
opacity: 0;
} [/css]
FireFox3.5ではまだアニメーションは未対応 また、アニメーションを利用するとiPhoneだとメインメニュークリック時に、 サブメニューが現れる前にリンクしてしまう。 逆に言えば、iPhoneはhoverの挙動はクリックすると状態がキープされるようだ。
次もポイントで、liをロールオーバーした時にul(第2階層)を表示する。 ここで第2階層をFadeアニメーションするために、opacity=1とtransitionを設定 [css]
visibility: visible;
opacity: 1;
-moz-transition: all 0.3s ease-in-out;
-webkit-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
} [/css]
「li:hover > ul」は新しい書き方ですね。 transitionのプロパティはActionScriptと同じぽいですね。 これもECMAScript準拠なのかね?
第2階層の外枠のレイアウトは#menuから絶対座標に指定 [css]
position: absolute;
font-size: 12px;
margin: 0;
padding: 0;
left: 0;
width: 185px;
border: solid 1px #ffffff;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
border-radius: 6px;
} [/css]
第2階層のメニューのレイアウト [css]
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.8);
padding: 8px 10px;
}
float: none;
margin: 0;
padding: 0;
background: -moz-linear-gradient(top, rgba(66, 110, 161, .8), rgba(66, 110, 161, .8));
background: -webkit-gradient(linear, left top, left bottom, from(rgba(66, 110, 161, .8)), to(rgba(66, 110, 161, .8)));
} [/css]
第2階層の外枠に沿うように、最初と最後のメニューは上下の角丸をつける [css]
-webkit-border-top-left-radius: 6px;
-moz-border-radius-topleft: 6px;
-webkit-border-top-right-radius: 6px;
-moz-border-radius-topright: 6px;
}
-webkit-border-bottom-left-radius: 6px;
-moz-border-radius-bottomleft: 6px;
-webkit-border-bottom-right-radius: 6px;
-moz-border-radius-bottomright: 6px;
} [/css]
このサンプルの問題点は、階層が増える毎に追加してやらないといけないけど、 何階層にもなるメニューは現実的ではないので、ある程度力技でもいいのかなと? その分ソースわかりにくくなるけど。
level1、level2をclassとして作ってみたけど、WebKit側で思った動作が得られなかった。 どうしても複数階層に対応するなら、JavaScriptやPHP等で動的にCSSを書き出すって感じ?
本当は、CSSも使いまわしのできる関数・プロパティやクラス化できれば、 リファクタリングできてライブラリ化できそうなんだけどなぁ。