画像置換を用いた横型メニュー rev.2

画像置換を用いた横型メニューについて、新しく書き直しました。 このページの内容は古いですので、新しい方を参照してください。

画像置換を用いた横型メニュー (最新版)

画像置換を用いた横型のメニューのサンプルです。 rev.1 では list-style-image プロパティを利用して似たような横型メニューを作成していましたが、キーボードを利用して選択する際に表示がおかしくなる、PSP では表示がおかしくなる、などの現象があったので対策を行いました。

画像の置換方法ですが、置換を行う要素の ::before 擬似要素に、CSS の content プロパティで画像を設定するという方法をとっています。 要素の width、height を画像のサイズに合わせておくことで、元の文字は画像に押し出されて表示領域外に出て行きます。 画像が非表示設定の場合は押し出されずに文字が表示領域に残ります。

また、content プロパティを使えない Internet Explorer の 6 や 7 に対しては、list-style-image プロパティを利用した方法で対応しています。

Sample

画像置換を用いた横型メニューの表示サンプル (Opera 9.5)

実際に動くサンプルは コチラ にあります。

CSS オン、画像表示の環境なら大抵のブラウザで問題なく表示されると思います。 なお、一番右端は、画像が読み込めなかった場合の表示のサンプルとしてわざと存在しない画像ファイルを指定しています。

Source

HTML Code

サンプルの HTML コードです。

ul 要素の下に li 要素、さらにその下に a 要素、というシンプルな構成です。 各 a 要素を CSS から参照するためにクラス名の設定を行っていますが、属性値による CSS セレクタが使えるブラウザが一般的になったら、href 属性の値で各 a 要素を参照する、という方法を採るといいかもしれません。 とりあえず現在は IE6 が居るからダメですけど(´・ω・`)

ir.htm のソースコード
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta http-equiv="Content-Style-Type" content="text/css" />
    <title>画像置換を用いた横型メニューのサンプル</title>
    <link type="text/css" charset="UTF-8" rel="stylesheet" media="screen" href="ir.css" />
    <!--[if IE 6]><link type="text/css" charset="UTF-8" rel="stylesheet" media="screen" href="ir_ie67.css"><![endif]-->
    <!--[if IE 7]><link type="text/css" charset="UTF-8" rel="stylesheet" media="screen" href="ir_ie67.css"><![endif]-->
    <!--[if IE 8]><link type="text/css" charset="UTF-8" rel="stylesheet" media="screen" href="ir_ie8.css"><![endif]-->
  </head>
  <body>
    
    <p>画像置換を用いた横型メニューのサンプルです。
      <br />解説ページは
      <a href="../horizontalMenu.htm" title="画像置換を用いた横型メニュー">コチラ</a>
      です。</p>
    
    <ul id="imageReplacing">
      <li class="home"><a href="../horizontalMenu.htm">HOME</a></li>
      <li class="about"><a href="../horizontalMenu.htm">このサイトについて</a></li>
      <li class="sample1"><a href="../horizontalMenu.htm">sample1</a></li>
      <li class="sample2"><a href="../horizontalMenu.htm">画像なし sample</a></li>
    </ul>
    
  </body>
</html>

CSS Code

サンプルの CSS コードです。

border や背景色の設定を行っているのでごちゃごちゃしてますが、重要な部分は強調している部分です。 それと各画像の URL の指定を行っている部分と。

ir.css のソースコード
@charset "UTF-8"; /* 文字コード宣言 */

a {
  text-decoration: none;
}
* {
  background-repeat: no-repeat;
}

ul#imageReplacing {
  overflow: hidden;
  list-style: none;
  width: 604px; height: 30px;
  padding: 0px; margin: 20px;
  font-size: 14px;
  border-style: solid none double solid;
  border-color: #46251A;
  border-width: 1px 0px 3px 1px;
  /*position: absolute; top: 300px; 絶対配置でも問題なし*/
}

#imageReplacing li {
  float: left;
  overflow: hidden;
  width: 150px; height: 30px; /* 画像の大きさ */
  border-right: 1px solid #46251A;
  position: relative;
}
#imageReplacing li a {
  height: 30px;
  width: 150px;
  overflow: hidden;
  display: block;
  background-color: #FFF1CC;
}
#imageReplacing li a:hover, 
#imageReplacing li a:focus, 
#imageReplacing li a:active {
  background-color: #F4EFCA;
}
#imageReplacing li a:before {
  display: block;
  float: left;
  color: #333333;
}
/* IE6 に以下のプロパティが適用されるとうまく動かないため子選択セレクタ ">" で IE6 には
  認識されないようにする */
#imageReplacing li>a:hover:before, 
#imageReplacing li>a:focus:before, 
#imageReplacing li>a:active:before {
  margin-left: -150px;
  /*position: absolute; /* IE 8 用: この指定をしないと margin-left: -150px; が有効にならない? 
    が、Opera ではこの指定をするとキーボードでの選択時に、領域が左に 150px 大きくなってしまう.
    よって条件付コメントで IE 8 にのみ適用 */
}
/* "home" ボタン設定 */
#imageReplacing li.home a:before {
  content: url("ir_home.png");
}
/* "about" ボタン設定 */
#imageReplacing li.about a:before {
  content: url("ir_about.png");
}
/* "sample1" ボタン設定 */
#imageReplacing li.sample1 a:before {
  content: url("ir_sample1.png");
}
/* "sample2" ボタン設定 */
#imageReplacing li.sample2 a:before {
  content: url("none.png");
}

それなりに Web 標準に近いブラウザはこれだけで大丈夫なのですが、Internet Explorer という糞ブラウザでは期待通りに動かないので、IE 用に CSS を書く必要があります。

IE8 beta2 はずいぶんと Web 標準に従うようになったので、1 つだけプロパティを加えれば動くようになります。 beta1 から beta2 で大幅な改良があったので、製品版では IE8 用に CSS を書かなくても動くようになることが期待できます。

ir_ie8.css のソースコード
@charset "UTF-8"; /* 文字コード宣言 */

#imageReplacing li a:hover:before, 
#imageReplacing li a:focus:before, 
#imageReplacing li a:active:before {
  position: absolute; /* この指定をしないと margin-left: -150px; が有効にならない? 
    が、Opera ではこの指定をするとキーボードでの選択時に、領域が左に 150px 大きくなってしまう.
    よって条件付コメントで IE 8 にのみ適用 */
}

IE6IE7 は CSS の content プロパティに対応していないので、それなりに CSS を書く必要があります。 が、画像は共通で使用できるので、それほど手間にはならないでしょう。

ir_ie67.css のソースコード
@charset "UTF-8"; /* 文字コード宣言 */

#imageReplacing li a { /* IE 7 用 */
  display: list-item;
  list-style: disc inside; /* none を設定すると画像も表示されなくなる. */
  vertical-align: bottom;
  line-height: 31px; /* 画像が非表示の場合の文字の位置調節. 画像の高さより 1px 大きめに設定 */
  margin-left: -300px;
  padding-left: 300px;
}
#imageReplacing li a:hover, 
#imageReplacing li a:focus, 
#imageReplacing li a:active {
  background-position: -150px 0px;
}

#imageReplacing li.home a {
  background-image: url("ir_home.png");
  list-style-image: url("ir_home.png");
}

#imageReplacing li.about a {
  background-image: url("ir_about.png");
  list-style-image: url("ir_about.png");
}

#imageReplacing li.sample1 a {
  background-image: url("ir_sample1.png");
  list-style-image: url("ir_sample1.png");
}

#imageReplacing li.sample2 a {
  list-style-image: url("none.png");
  background-image: url("none.png");
}

使用した画像

サンプルに使用した画像は以下です。

通常時に表示する画像と、ロールオーバーに使用する画像をまとめておいて、マウスオーバー時には負のマージンでずらすことでロールオーバーを実現しました。

ブラウザの対応状況

Firefox 3期待通りの動作
Firefox 2期待通りの動作
Opera 9.5期待通りの動作
Safari 3期待通りの動作
IE8 beta2 期待通りの動作? ただし IE8 用に CSS を書く必要がある
リロードすると画像が消えたりどうもおかしな挙動です
IE7期待通りの動作. ただし IE6, 7 用に CSS を書く必要がある
IE6期待通りの動作. ただし IE6, 7 用に CSS を書く必要がある
IE5.5 IE5.5 用の CSS を書くことで、似たような動作をさせることが可能. ただし画像非表示の場合に何も表示されない また、もともと画像置換を行わないような CSS を書くことも可能. 好みで選択することになります
PSP 搭載ブラウザ画像置換が行われない. 文字は表示され、通常通りリンクとして機能

モダンブラウザでは問題なく表示されます。 IE6 と IE7 も対策をしていますので一応期待通りの動作をします。

問題は IE5.5 ですね。 IE5.5 はもはやどうでもいい、と言うとあれですが、まあ IE5.5 でも画像を表示させたいなら適当に CSS を書けば一応対応はできると思います。

あと IE8 beta2 はどうなんだろう。 一応ちゃんと動くみたいなんですが、たまにちゃんと動かなくなったり。 意味がわかりません・・・

関連項目


'08.09.20 IE6 でも IE7 と同じ CSS で動く方法を見つけたので変更した.
'08.09.18 rev.2 を作成。 content プロパティを主に使うように変更した.