個人的に決定版だと思う画像置換

Web制作時に画像置換してますか?画像置換とは通常表示される文字列などの代わりに画像を表示するためのテクニックです。

画像置換は個人的には必須のテクニックだと思っています。なぜに必須なのかと言えば「コンテンツはHTML、デザインはCSS」だからです。

コンテンツとデザインを完全に分離させるために避けて通れないのが、コンテンツでありデザインでもある文字列の扱いです。

情報として文字列は表示すべきだが、見た目はきれいにデザインしたいという場合、現在、正式に勧告されているCSS2.1のプロパティだけでは役不足です(CSS3が正式に勧告されてブラウザがきちんと対応すれば改善されるでしょう)。そこで画像置換というテクニックが必要になります。

念のため自分の考えを言っておきますが、画像置換はスパム的なテクニックではなく、要は使う側の使い方次第だと思ってます。なぜなら、画像を表示するために使用されるimg要素のalt属性(代替文字列)にどんな文字列を入れるのかも、使う側の使い方次第だからです。

img要素を使うこと自体がスパム的だと言う内容を見たことがありません。が、画像置換がスパム的だとする内容は多くあります。ただ、それは画像置換する際に配慮が欠けているってだけのことです。

つまり、ユーザーやHTMLを利用したプログラム(サーチエンジン等)を騙すのが目的ではなく、様々なケースを想定して、問題なく情報が取得できるよう配慮すれば、画像置換すること自体に問題はないと考えています。

では、問題なく情報を取得できるよう配慮した画像置換の方法を解説していきたいと思います。

画像置換の肝は表示したい画像で「押し出す」ことと「重ねる」ことです。実際適用したサンプルは最後の方にリンクを貼っておきます。

シンプルな画像置換

サンプルで使用しているgif画像(240x30)
「テキストの画像置換」と書かれたイメージ

まずはモダンブラウザ(:before疑似要素が使えるブラウザ)で有効な画像置換です。画像の表示範囲を確保し、:before擬似要素で画像を表示しつつ文字列を押し出します。文字列と画像を重ねる訳ではないので、透明・半透明の画像が使用できます。仮に画像が表示されなかった場合、押し出されなかった文字列が表示されます。

HTML
<p id="ir1-1">テキストの画像置換</p>
CSS
#ir1-1 {
  width: 240px;
  height: 30px;
  overflow: hidden;
}
#ir1-1:before {
  content: url(ir1.gif);
}

次にレガシーブラウザでも有効な画像置換です。1つ目は:before擬似要素とcontentプロパティの代わりにlist-styleプロパティのマーカー画像を使って文字列を押し出す画像置換です。list-styleプロパティを指定する子要素(span要素など)を追加する必要があります。

HTML
<p id="ir1-2"><span>テキストの画像置換</span></p>
CSS
#ir1-2 {
  width: 240px;
  height: 30px;
  overflow: hidden;
}
#ir1-2 span {
  display: list-item;
  list-style: disc url(ir1.gif) inside;
}

2つ目は子要素(span要素)を親要素(a要素)の背面に配置し、親要素(a要素)に背景画像を指定して文字列を隠す画像置換です。画像が表示されなかった場合は背面にある文字列が見えるようになります。当然ですが、透明・半透明の画像は使用できません。

HTML
<p id="ir1-3"><span>テキストの画像置換</span></p>
CSS
#ir1-3 {
  width: 240px;
  height: 30px;
  overflow: hidden;
  background: url(ir1.gif) no-repeat 0 0;
}
#ir1-3 span {
  position: relative;
  z-index: -1;
}

画像置換でロールオーバーイメージ

サンプルで使用しているgif画像(240x160)
「リンクの画像置換」と書かれたイメージスプライト
余白になっている部分は透明になっている箇所です。

上記の「シンプルな画像置換」とイメージスプライト(複数の画像を1つにまとめたもの)を組み合わせるとロールオーバーイメージができます。

まずは:before擬似要素を使用した、モダンブラウザで有効な画像置換です。ポイントはcontentプロパティとbackgroundプロパティで同じ画像を指定することです。まず、contentプロパティによって表示される画像で文字列を押し出します、この時点で表示されるのは画像の透明な部分です。

実際に表示させる画像の部分はbackgroundプロパティで指定します。:hover擬似クラスとbackground-positionプロパティで画像の位置をずらしてあげればロールオーバーイメージが出来上がります。

イメージスプライトを使用するのは以下の2つの理由からです。

  • 「押し出す」「表示する」「ロールオーバーする」の3つを別々の画像にすると、いずれかの画像が表示されなかった場合に支障が出る可能性がある
  • 画像を一度にキャッシュする
HTML
<p id="ir2-1"><a href="#chapter2">リンクの画像置換</a></p>
CSS
#ir2-1 a {
  display: block;
  width: 240px;
  height: 30px;
  overflow: hidden;
}
#ir2-1 a:before {
  display: inline-block;
  content: url(ir2.gif);
  background: url(ir2.gif) no-repeat 0 -40px;
}
#ir2-1 a:hover:before {
  background-position: 0 -80px;
}
#ir2-1 a:active:before {
  background-position: 0 -120px;
}

次にレガシーブラウザでも有効な画像置換です。1つ目はcontentプロパティの代わりにlist-styleプロパティのマーカー画像を使ったものです。

HTML
<p id="ir2-2"><a href="#chapter2"><span>リンクの画像置換</span></a></p>
CSS
#ir2-2 a {
  display: block;
  width: 240px;
  height: 30px;
  overflow: hidden;
  background: url(ir2.gif) no-repeat 0 -40px;
}
#ir2-2 a:hover {
  background-position: 0 -80px;
}
#ir2-2 a:active {
  background-position: 0 -120px;
}
#ir2-2 a span {
  display: list-item;
  list-style: disc url(ir2.gif) inside;
}

2つ目は親要素の背面に子要素を配置する方法です。

HTML
<p id="ir2-3"><a href="#chapter2"><span>リンクの画像置換</span></a></p>
CSS
#ir2-3 a {
  display: block;
  width: 240px;
  height: 30px;
  overflow: hidden;
  background: url(ir2.gif) no-repeat 0 -40px;
}
#ir2-3 a:hover {
  background-position: 0 -80px;
}
#ir2-3 a:active {
  background-position: 0 -120px;
}
#ir2-3 a span {
  position: relative;
  z-index: -1;
}

ボタンの画像置換

サンプルで使用しているgif画像(240x120)
「ボタンの画像置換」と書かれたイメージスプライト
余白になっている部分は透明になっている箇所です。

ボタンの画像置換は、ボタンの文字をオフレフトで隠し、隠した文字と同じ文字を擬似要素とcontentプロパティで表示し、その上に背景画像を指定したボタンをpositionプロパティで重ねるという、ちょっとトリッキーな方法で実現しています。擬似要素に対応しているブラウザのみが対象です。

HTML
<p id="ir3"><input type="button" value="ボタンの画像置換" /></p>
CSS
#ir3 {
  position: relative;
  width: 240px;
  height: 30px;
  overflow: hidden;
}
#ir3:before {
  margin-top: -0.5em;
  padding: 15px 0;
  display: inline-block;
  width: 240px;
  line-height: 1;
  content: "ボタンの画像置換";
  text-align: center;
}
#ir3 input {
  margin: 0;
  padding: 0;
  border: 0;
  position: absolute;
  top: 0;
  left: 0;
  width: 240px;
  height: 30px;
  background: transparent url(ir3.gif);
  text-indent: -10em;
  text-align: left;
  cursor: pointer;
}
#ir3 input:hover {
  background-position: 0 -40px;
}
#ir3 input:active {
  background-position: 0 -80px;
}

擬似要素に対応していないブラウザで画像置換する代替案の一例としては、イメージボタンをJavaScript(jQueryなど)で追加して、通常表示されるボタンと重ねるというのはどうでしょうか。イメージに透過gifを指定すれば、大きさや背景画像などが自由にアレンジできそうですよ。

HTML
<p>
  <input type="submit" value="submit" /><!-- 通常表示されるボタン -->
  <input type="image" src="spacer.gif" alt="" /><!-- JavaScriptで追加する透過gifボタン -->
</p>

チェックボックスの画像置換

サンプルで使用しているgif画像(500x16)
チェックボックスのイメージスプライト
余白になっている部分は透明になっている箇所です。

cssでデザインできないチェックボックスの画像置換です。input要素の上にlabel要素を重ね合わせ、backgroundプロパティで指定した画像でチェックボックスを隠します。チェックボックスがはみ出さないように、少し大きめに画像を作る必要があります。

CSS3で新たに追加された:checked擬似クラスで、チェックされているかどうかを判定します。CSS3に対応していないレガシーブラウザには通常のチェックボックスが表示されるよう:root擬似クラスから始まるセレクタでプロパティを適用しています。

input要素に指定したwidthプロパティとheightプロパティが14pxなのはFirefoxが13px未満に設定できないためです。奇数の処理はブラウザ毎に差異があるため、13pxではなく14pxにしています。

レガシーブラウザにも対応させたい場合は、JavaScriptを使用してcheckedクラスを追加・削除するというのが良さそうです。

ちなみに、サンプルではlabel要素の最大幅を160pxとしてイメージスプライトを作成しています。

HTML
<ul id="ir4">
  <li><input type="checkbox" name="checkbox" checked="checked" id="checkbox1" /><label for="checkbox1">チェックボックス1</label></li>
  <li><input type="checkbox" name="checkbox" id="checkbox2" /><label for="checkbox2">チェックボックス2</label></li>
</ul>
CSS
:root #ir4 li input {
  margin: 0 -14px 0 0;
  padding: 0;
  border: 0;
  width: 14px;
  height: 14px;
  vertical-align: middle;
}
:root #ir4 li label {
  padding: 1px 0 1px 20px;
  display: inline-block;
  max-width: 140px;
  min-height: 16px;
  vertical-align: middle;
  background: url(ir4.gif) no-repeat 0 50%;
  cursor: pointer;
}
:root #ir4 li label:hover,
:root #ir4 li label:focus {
  background-position: -160px 50%;
}
:root #ir4 li input:checked+label {
  background-position: -320px 50%;
}
:root #ir4 li input:checked+label:hover,
:root #ir4 li input:checked+label:focus {
  background-position: -480px 50%;
}

ラジオボタンの画像置換

サンプルで使用しているgif画像(500x16)
ラジオボタンのイメージスプライト
余白になっている部分は透明になっている箇所です。

チェックボックスの画像置換と同様の方法でラジオボタンも画像置換できます。

HTML
<ul id="ir5">
  <li><input type="radio" name="radio" checked="checked" id="radio1" /><label for="radio1">ラジオボタン1</label></li>
  <li><input type="radio" name="radio" id="radio2" /><label for="radio2">ラジオボタン2</label></li>
</ul>
CSS
:root #ir5 li input {
  margin: 0 -14px 0 0;
  padding: 0;
  border: 0;
  width: 14px;
  height: 14px;
  vertical-align: middle;
}
:root #ir5 li label {
  padding: 1px 0 1px 20px;
  display: inline-block;
  max-width: 140px;
  min-height: 16px;
  vertical-align: middle;
  background: url(ir5.gif) no-repeat 0 50%;
  cursor: pointer;
}
:root #ir5 li label:hover,
:root #ir5 li label:focus {
  background-position: -160px 50%;
}
:root #ir5 li input:checked+label {
  background-position: -320px 50%;
}
:root #ir5 li input:checked+label:hover,
:root #ir5 li input:checked+label:focus {
  background-position: -480px 50%;
}

実際適用したサンプル

ここで紹介したのは、基本的な画像置換の考え方とその一例です。色々アレンジして使用してみてください。