メニューの最近のブログ記事
小技の効いたサイトを発見しました。
このサイトで、左のメニューにカーソルを合わせると英語表記のところがゆっくりと色が変化していくのがわかると思います。トランジション効果と言えばよいのでしょうか、アニメーション処理がしてあります。
このサイトの場合は、画像のロールオーバー時に、JavaScriptでアニメーション処理をしていると思うのですが、今回画像なしで似たような動作をやってみます。CSS3とそれに対応しているブラウザを使用します。残念ながら現在はSafari4.0とGoogle Chomeしか動作しないようです。
サンプル
動作確認
Google Chrome 4.0、Safari 4.0.4 for Windows XPです。
CSS3はまだ正式勧告されていないので、使用する場合にはプロパティの前にベンダープリフィックスと呼ばれる接頭辞をつける必要があります。SafariおよびChomeは「-webkit-」です。
(X)HTMLコード
<ul>
<li><a href="concept.html">コンセプト<span><br />CONCEPT</span></a></li>
<li><a href="menu1.html">メニュー<span><br />MENU</span></a></li>
<li><a href="">新着・お得情報<br /><span>NEW&EVENTS</span></a></li>
<li><a href="">お問合せ・ご予約<br /><span>CONTACT</span></a></li>
<li><a href="info.html">店舗情報・地図<br /><span>INFORMATION</span></a></li>
</ul>
CSSコード
ul {
width:200px;
background:#735D4A;
margin:0;
padding:0 10px;
}
li {
list-style:none;
border-bottom:#524139 1px solid;
}
li:last-child {
border-bottom:none;
}
li a {
display:block;
padding:15px 0 15px 30px;
font-family:"MS 明朝",serif;
color:#F7F3EF;
font-size:14px;
text-shadow:2px 2px 2px rgba(0,0,0,0.6);
-moz-text-shadow:2px 2px 2px rgba(0,0,0,0.6);
-webkit-text-shadow:2px 2px 2px rgba(0,0,0,0.6);
line-height:1.4;
letter-spacing:1px;
background:url("bg_list.gif") 10px 50% no-repeat;
text-decoration:none;
outline: none;
}
li a span {
color:#080808;
font-family: "arial",sans-serif;
font-size:10px;
text-shadow:none;
-moz-text-shadow:none;
-webkit-text-shadow:none;
-webkit-transition-duration:0.4s;
}
li a:hover span {
color:#F79239;
}
「-webkit-transition-duration:0.4s」というのがアニメーション部分の指定になります。メニューをマウスオーバーしたときに、英語表記の部分だけが0.4秒かけて色がゆっくりと変わります。
また、CSS3のテキストにシャドーをつけれる「text-shadow」、親子関係の最後の子要素だけに適用する「:last-child」も併せて使用しています。
CSS HappyLifeの平澤さんが新しいサイト「CSS HappyLife ZERO」をオープンされたのですが、そのメニュー部分がとても素敵だったので、参考に同じようなものを作ってみました。
ちなみに全くソースコードは拝見していませんので、同じようには作られてはいないと思います。
前回の記事「アクセシビリティの高いCSSロールオーバーメニュー」を参考にすれば、比較的簡単に作れそうです。
サンプル
動作確認
Firefox3.5.7、Google Chrome 3.0、Safari 4.0.4 for Windows XPです。IE6はhoverに対応していませんので、強調する効果は得られませんが、不具合なく表示する事はできます。Opera 10.10は正常に動作しません。なぜでしょう。「ul#menu li a」に「display:inline-block;」を追加するとちゃんと動作しました。
(X)HTMLコード
<ul id="menu">
<li class="menu1"><a href="#" class="current"><img src="images/menu1.gif" alt="menu1" /></a></li>
<li class="menu2"><a href="#"><img src="images/menu2.gif" alt="menu2" /></a></li>
<li class="menu3"><a href="#"><img src="images/menu3.gif" alt="menu3" /></a></li>
<li class="menu4"><a href="#"><img src="images/menu4.gif" alt="menu4" /></a></li>
<li class="menu5"><a href="#"><img src="images/menu5.gif" alt="menu5" /></a></li>
</ul>
CSSコード
img {
border:0;
}
ul#menu {
float:left;
margin:0;
padding:0;
}
ul#menu:hover {
background: url(images/bg_menu_hover.gif) no-repeat;
}
ul#menu li {
float:left;
margin:0;
padding:0;
list-style:none;
}
ul#menu li a {
display:block;
display:inline-block;
width:100px;
height:30px;
}
ul#menu li a:hover,
ul#menu li a.current {
background-image:url(images/bg_menu_on.gif);
}
ul#menu li.menu1 a:hover,
ul#menu li.menu1 a.current {
background-position:0 0;
}
ul#menu li.menu2 a:hover,
ul#menu li.menu2 a.current {
background-position:-100px 0;
}
ul#menu li.menu3 a:hover,
ul#menu li.menu3 a.current {
background-position:-200px 0;
}
ul#menu li.menu4 a:hover,
ul#menu li.menu4 a.current {
background-position:-300px 0;
}
ul#menu li.menu5 a:hover,
ul#menu li.menu5 a.current {
background-position:-400px 0;
}
ul#menu li img {
position:relative;
z-index:-1;
}
考え方としては、リスト(ul)の背景に目立たない用のリスト画像を指定し、特定のメニューにカーソルがあったときはそのメニューだけオンマウス用の画像に切り替え、他のメニューはリストの一番下に回りこませてることにより目立たない用のリスト画像が表示されるというわけです。
また、現在表示しているページのメニューも目立たせたい場合は、a要素にcurrentというクラス名をつけて、CSSのほうで個別にスタイルを指定するとよいと思います。
基本のHTMLソースコードは以下のとおりです。divでリストを囲まなくてもよいですが、メニュー部分ということがわかりやすいですし、デザインに幅が広がります。 class名は「section」でなくて、「menu」や「submenu」などでもよいです。
(X)HTMLコード
<div class="section">
<h2>メニュー</h2>
<ul>
<li><a href="#">HOME</a></li>
<li><a href="#">最新情報</a></li>
<li><a href="#">事業内容</a></li>
<li><a href="#">会社概要</a></li>
<li><a href="#">採用情報</a></li>
<li><a href="#">お問い合わせ</a></li>
</ul>
</div><!-- /section -->
デザイン案1
ではデザインです。まずは基本ということで、リストマークを画像化、テキスト部分がアンカーになっているデザインにします。
サンプル
CSSコード
div.section {
width:200px;
padding:3px;
background:#E7E7E7;
}
div.section h2 {
margin:0;
font-size:12px;
color:#fff;
line-height:3.0;
padding:2px 5px 0px 5px;
background:#3C3C3C;
}
div.section ul{
margin:5px 0 0 0;
padding:0;
list-style:none;
}
div.section li{
margin:0 0 0 5px;
padding-left:10px;
font-size:12px;
line-height:2.0;
border-bottom:1px solid #fff;
background:url(bg_list.gif) 0 50% no-repeat;
}
div.section a {
color:#5A5D00;
text-decoration:none;
}
div.section a:hover {
color:#7B8200;
border-bottom:1px solid #7B8200;
}
リストマークを画像化するためには、ulでlist-style(-type)をnoneにし、liの背景画像でリストを表示するのが一般的です。リストの位置は、background-posionで指定(今回は一括指定しています。)、リストとテキストの余白はliのpadding-leftで調整します。
デザイン案2
上記の場合、アンカー領域がテキスト部分のみなので、人によってはクリックしにくい場合もあるかもしれません。そういう場合は、リスト部分をアンカー領域にしてクリックしやすくします。
サンプル
CSSコード
div.section {
width:200px;
padding:3px;
background:#E7E7E7;
}
div.section h2 {
margin:0;
font-size:12px;
text-align:center;
background:#295DAD url(bg_h2.gif) 0 0;
line-height:3.0;
color:#fff;
}
div.section ul {
margin:0;
padding:0;
list-style-type:none;
}
div.section li {
margin:0;
padding:0;
font-size:12px;
color:#333;
padding-bottom:1px;
background:#fff url(bg_dotline.gif) 0 100% repeat-x;
}
div.section li a {
display:block;
color:#7C9C2D;
padding:10px 0 10px 20px;
background:#fff url(bg_list.gif) 5px 50% no-repeat;
}
div.section li a:hover {
color:#9CC23D;
background:#fff url(bg_list.gif) 5px 50% no-repeat;
}
ポイントは、a要素を「display:block;」でブロック要素にすることです。そして、リストの画像をli要素ではなくa要素に指定する事です。こうすることで、リストマークのところまでクリックできるようになります。
これまでロールオーバーメニューをCSSのみで作ろうとした場合、ちらつきが起こったり、画像をオフにしていたら見れなかったり、アクセシビリティが低くなってしまっていました。
しかし、ある程度これらを克服したCSSの書き方がありました!しかも非常にCSSソースコードがコンパクトになっています。
ピュアCSSで実装するDKIRを応用した画像ボタンのロールオーバー効果 | CSS-EBLOG
詳細は上記のブログを参考にしていただければと思います。
ポイントは画像の使い方でしょうか。 HTMLにて<img src="" alt="" />でマウスオーバー前の画像を表示、CSSにて背景画像でマウスオーバー時の画像を配置し、マウスオーバー時に表示する範囲をbackground-positionで設定しています。
これらの画像をz-indexでレイヤーの順番を変更にする事で、重なった画像がうまく表示されるという仕組みですね。
本来display:-9999pxで画面外にとばしてしまうところですが、うまく下のレイヤーに隠すとはなかなか面白いですね。
altでメニューの代替テキストを表示することで、画像がオフだったり読み込まれないときでも一応読めます。
また、最初からマウスオーバー時の画像を読み込んでいるので、マウスオーバー時にちらつきが発生することもありません。
難点は画像を作るのが面倒ってことですかね。メニュー個別に分かれたマウスオーバー前の画像と、マウスオーバー時の全てのメニューがくっついた画像を用意しないといけないのは、少し手間がかかりますね。その分、CSSソースコードはシンプルになるのですが。
ソースコードを引用させていただきます。
(X)HTMLコード
<ul id="menu">
<li class="home"><a href="#"><img src="btn_home.png" alt="HOME" /></a></li>
<li class="product" id="current"><a href="#"><img src="btn_product.png" alt="Product" /></a></li>
<li class="about"><a href="#"><img src="btn_about.png" alt="About" /></a></li>
<li class="blog"><a href="#"><img src="btn_blog.png" alt="Blog" /></a></li>
<li class="contact"><a href="#"><img src="btn_contact.png" alt="Contact" /></a></li>
</ul>
CSSコード
#menu li {
float: left;
position: relative;
z-index: 3;
}
#menu li a {
background: url(menu.png) left top no-repeat;
display: -moz-inline-box; /* Firefox2 用のスタイル */
display: inline-block;
}
#menu li.product a { background-position: -135px 0; }
#menu li.about a { background-position: -255px 0; }
#menu li.blog a { background-position: -375px 0; }
#menu li.contact a { background-position: -495px 0; }
#menu li a:hover {
position: static;
}
#menu li a:hover img ,
#menu li#current a img {
position: relative;
z-index: -1;
}
参考サイト
横並びのメニューで、左側あるいは右側にmarginで余白を空けた際、最初あるいは最後のメニュー部分だけ余白は必要ではありませんよね。classを指定しないで余白を消す方法です。

first-childあるいはlast-childセレクタを使用すれば簡単に実現できますが、IE6など一部のブラウザでは対応していません。そこで、ネガティブマージンを使用することで、無駄にclassを指定することなく、最後の余白だけ消すことが出来ます。
(X)HTMLコード
<div class="menu">
<ul>
<li>メニュー1</li>
<li>メニュー2</li>
<li>メニュー3</li>
<li>メニュー4</li>
</ul>
</div >
CSSコード
div.menu {
width:430px;
border: solid 1px #000;
}
div.menu ul {
margin:0;
padding:0;
margin-right:-10px;
overflow:hidden;
list-style:none;
zoom:1;
}
* html div.menu ul { /* for IE6 */
margin-right:-20px;
}
div.menu ul li {
float:left;
width:100px;
margin-right:10px;
padding:10px 0;
text-align:center;
background:#ddd;
}
liにmargin-right:10px;を指定して右側に余白を空け、ulにmargin-right:-10px;を指定してリストの一番右側の余白を相殺します。
IE6ではfloatしたボックスのmarginの値が2倍になるバグがあるので、* htmlハックを利用してIE6用に、2倍の-20pxをulの右側の余白に指定します。このバグを回避する方法はいくつかあるのですが(例えば「display:inline;」を指定する)、今回はこのような処置を取ります。
IE6でネガティブマージンを有効にするために「zoom:1;」を指定します。これはhasLayoutプロパティの値をtrueにするためです。hasLayoutに関しては、以下のサイトなどを参考にしてください。
ウノウラボ Unoh Labs: hasLayoutとは何か
floatを解除するのに「overflow:hidden;」を使用していますが、以下のページに書いてあるような方法でも構いません。
ドロップダウンメニューのようなダイナミックな動作は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
参考サイト
前回、CSSのみでロールオーバー効果のメニューを作る方法を紹介しましたが、カーソルを合わせたときの画像を、カーソルを合わせた瞬間に呼び出しているので、一瞬ですが読み込みのためちらつきが発生します。
それを回避するために、カーソルを合わせてたときに表示される画像を、ページが表示されたときにあらかじめ呼び出しておく方法があります。
使用する画像は以下のものです。メニューで使用する画像がすべてくっついています。

それでは、サンプルとソースコードを見ていきましょう。
サンプル
(X)HTMLコード
<ul class="menu">
<li class="menu1"><a href="">メニュー1</a></li>
<li class="menu2"><a href="">メニュー2</a></li>
<li class="menu3"><a href="">メニュー3</a></li>
</ul>
CSSコード
ul.menu {
margin:0;
padding:0;
}
ul.menu li {
float:left;
text-indent:-9999px;
overflow:hidden;
list-style:none;
}
ul.menu li a {
display:block;
width:150px;
height:30px;
}
li.menu1 a {
background:url(menu.gif) 0 0 no-repeat;
}
li.menu1 a:hover {
background:url(menu.gif) 0 -30px no-repeat;
}
li.menu2 a {
background:url(menu.gif) -150px 0 no-repeat;
}
li.menu2 a:hover {
background:url(menu.gif) -150px -30px no-repeat;
}
li.menu3 a {
background:url(menu.gif) -300px 0 no-repeat;
}
li.menu3 a:hover {
background:url(menu.gif) -300px -30px no-repeat;
}
/* モダンブラウザ(Firefox Opera Safari)対策 */
ul.menu:after {
content:".";
display:block;
height:0;
clear:both;
visibility:hidden;
font-size:0;
}
/* Win版IE7とMac版IE5対策 */
ul.menu {
display:inline-block;
}
/* Win版IE5および6対策 */
/* Hides from IE-mac \*/
* html ul.menu {
height:1px;
}
ul.menu {
display:block;
}
/* End hide from IE-mac */
backgroundプロパティで、表示する画像をずらしています。右や下にずらす場合はマイナス表示をしないといけないので注意です。
メニューを横並びにするのにfloatを使用している都合上、リスト以降の要素の回り込みを解除するためにclearfixハックを使っています。CSSソースコードの後半部分です。
3年くらい前(2006年頃)までは、メニューのロールオーバーにCSSを使うことがトレンドでした。しかしながら、テキストを画面外に飛ばし代替画像を表示する手法(画像置換法)のため、スパム行為に抵触するんじゃないかとの懸念から現在ではあまり使われなくなりました。
現在ではCSSの代わりにJavascriptを使用しているところが多いと思います。AJAX(エイジャックス:JavaScriptのHTTP通信機能を利用して非同期通信をするもの)の流行からJavascriptが脚光を浴び、「jQuery」や「Prototype」といったライブラリが登場し、多くのところからロールオーバー機能のついたライブラリが公開されています。
JavascriptもブラウザのほうでOFFにしていたら無効になるわけで、CSSもJavascriptも一長一短なところがあるのが現状です。
さて本題ですが、このロールオーバーの手法は、テキストにリンクがはってあることが条件になります。
サンプル
(X)HTMLコード
<ul class="menu">
<li class="menu1"><a href="">メニュー1</a></li>
<li class="menu2"><a href="">メニュー2</a></li>
<li class="menu3"><a href="">メニュー3</a></li>
</ul>
CSSコード
ul.menu {
margin:0;
padding:0;
}
ul.menu li {
float:left;
text-indent:-9999px;
overflow:hidden;
list-style:none;
}
ul.menu li a {
display:block;
width:150px;
height:30px;
}
li.menu1 a:link {
background-image:url(menu01.gif);
}
li.menu1 a:hover {
background-image:url(menu01_on.gif);
}
li.menu2 a {
background-image:url(menu02.gif);
}
li.menu2 a:hover {
background-image:url(menu02_on.gif);
}
li.menu3 a {
background-image:url(menu03.gif);
}
li.menu3 a:hover {
background-image:url(menu03_on.gif) ;
}
/* モダンブラウザ(Firefox Opera Safari)対策 */
ul.menu:after {
content:".";
display:block;
height:0;
clear:both;
visibility:hidden;
font-size:0;
}
/* Win版IE7とMac版IE5対策 */
ul.menu {
display:inline-block;
}
/* Win版IE5および6対策 */
/* Hides from IE-mac \*/
* html ul.menu {
height:1px;
}
ul.menu {
display:block;
}
/* End hide from IE-mac */
メニューを横並びにするのにfloatを使用している都合上、リスト以降の要素の回り込みを解除するためにclearfixハックを使っています。
CSSの読み込みの遅さを防ぐ
今回説明した方法だと、オンマウスにした瞬間ちらつきが発生します。その後は画像がキャッシュされるためちらつきは発生しなくなります。この問題を解決する手としては、オンとオフの画像をくっつけて作成し、部分的に呼び出す方法があるのですが、また別の機会に紹介します。
ちらつきのないCSSロールオーバーメニューを作る - CSSデザインノート
また、IE6などだとブラウザの設定によって毎回ページのキャッシュを取得するため、マウスを置いた際画像の読み込みが遅く、ちらついてしまう現象が起きます。この現象はFirefoxなどのほかのブラウザでは起こりません。
IE6対策に以下のコードをCSSファイルに記述します。
CSSコード
html {
filter: expression(document.execCommand("BackgroundImageCache",
false, true));
}
これは、CSSファイル中にJavascriptコードを書いているのですが、IEの独自の書き方です。他のブラウザでは無視されるのでハックの必要はありません。背景画像をキャッシュしています。
Javascriptでメニューのロールオーバーをしたいときは
本サイトの趣向とは違いますが、Javascriptでメニューのロールオーバーができるライブラリをいくつか紹介します。

