[Sass & Compass] Compass: CSS Sprite で画像ナビゲーションを作成する

Compass を使って、CSS Sprite による画像ナビゲーションを簡単に作成します。

以前に画像ナビゲーションを下記の方法で作成しました。

CSS: 画像ナビゲーションのマウスオーバー処理を visibility: hidden と Sass の @for で作る | deadwood

この方法では、例えば透過画像を使いたい場合に、下に敷いた画像が見えてしまいます。
赤がにじんでいるように見えます(下図、上の「よこなが」)。

2014-08-11_css-sprite_01

Compass を使った CSS Sprite で作ります。

CSS Sprite とは

Compass のドキュメント。

Compass Sprites | Compass Documentation

Compass を利用しない方法

Compass を利用しない場合、色々手間がかかります。
こちらが参考になりました。

CSSスプライトについてあれこれ。

メリットとデメリット

下記のようなメリットがあります。

コーダー必見、SCSS・Compassで開発効率アップ|便利なCSS Sprite実装編 | Developers.IO

CSS Spriteのメリット

  1. 画像をくっつけることによってHTTPリクエスト数の削減
  2. マウスオーバーなどで表示を切り替えるがスムーズ(個別に画像を読み込んでいる場合、切り替わったときに読み込みが発生します)
  3. CSSのみでボタンなどのアフォーダンスを切り替えることができる

CSS Spriteのデメリット

  1. 画像をまとめて作るのが手間
  2. 画像に変更があった場合、座標の変更が手間
  3. 画像をまとめる際に汎用性を考えどの座標に配置するか頭を使う
  4. デザインする際に書き出しようのファイルを作る必要がある
  5. alt属性は使えずテキストを置くことはできるが、テキストを見えなようにするテクニック(画像置換)は要注意

CSS Spriteは価値のあるテクニックですが上記のような手間のかかるものでもあります。
そこでSCSS・Compassを使うことでほとんどのデメリットを解消することができます。

準備

CSS Sprite を利用します。
今回は上図サンプルのように、縦横の大きさがバラバラの画像を利用し、マウスホバー処理をさせます。

Compass を設定する

config.rb で画像パスに関わる設定は以下あたりでしょうか。
relative_assets では、絶対パスから相対パスに変更します。

config.rb
http_path = "/"
images_dir = "images"
relative_assets = true

ちなみに Grunt で設定したい場合には、こちらを参考にすると良さそうです。

Compass+GruntでCSSスプライトを使う | chikathreesix

画像を切り出す

画像をパーツ毎に切り出しておきます。
対応する画像は .png のみです。

なお、下記のような画像 _hover を追加した画像を用意しておくと、css の :hover 処理まで行ってくれるのであらかじめ用意しておきます(詳しくは後述)。
ちなみに _active:active_target:target のコードが生成されます。

  • images /menus/y.png
  • images /menus/y_hover.png
  • images /menus/h.png
  • images /menus/h_hover.png

今回は menus というフォルダに画像を入れておきます。

Sprite Magic Selectors | Compass Documentation

このディレクトリ名は、Compass の記述内でも利用することになります。
マップ名とよばれるので <map> と以降記載します。

つかいかた

はじめに必要な設定を全て書き出すと下記のようになります。
CSS Sprite させる画像を span などにクラスを付けて用意しておきます。
ディフォルトで生成されるクラス名は、<map>-<ファイル名> になります。

<a href=""><span class="menus-h"></span></a>
<a href=""><span class="menus-v"></span></a>

Compass の機能を使って生成します。

/* CSS Sprite */
$menus-sprite-dimensions: true;
@import "menus/*.png";
@include all-menus-sprites;
span {
  display:inline-block;
}

おのおのの記述については以下で確認していきます。

マジックインポートでスプライト画像を生成する

マジックインポートで用意した画像ディレクトリをインポートすると、スプライト画像を自動生成してくれます。
@import "<map>/*.png"; の部分で、ディレクトリ名を指定します。

Spriting with Compass | Compass Documentation

画像は images/menus-s9b98db01ea.png といった名称で、下記のように生成されます。
キャッシュされると表示が乱れるので、生成毎にランダムなファイル名が付けられるようです。

2014-08-11_css-sprite_03

ファイル名とスタイルシートの内容を書き換えれば、下記のように変更もできるようです。
通常は必要なさそうですね。

css – How to turn off COMPASS SASS cache busting? – Stack Overflow

マジックセレクタでスプライト CSS を生成する

ミックスインでスプライト CSS を自動生成できます。
@include all-<map>-sprites;
各画像のクラスと background-position を計算してくれます。
:hover の CSS もよしなに生成してくれます。

画像の縦横サイズを測る

$menus-sprite-dimensions: true; を付けると、各画像の縦横サイズを自動で測り、CSS に書き加えてくれます。
この他にも、このような初期設定が用意されています(後述)。

結果

スプライト画像(上記)と、以下のようなCSSが生成されました。

/* CSS Sprite */
.menus-sprite, .menus-h, .menus-v {
  background-image: url('../images/menus-s9b98db01ea.png');
  background-repeat: no-repeat;
}
.menus-h {
  background-position: 0 0;
  height: 27px;
  width: 110px;
}
.menus-h:hover, .menus-h.h-hover {
  background-position: 0 -27px;
}
.menus-v {
  background-position: 0 -54px;
  height: 110px;
  width: 28px;
}
.menus-v:hover, .menus-v.v-hover {
  background-position: 0 -164px;
}
span {
  display: inline-block;
}

あとは各画像を position で位置調整すれば、必要な出力が得られます。

2014-08-11_css-sprite_02

スプライトの制御とカスタマイズ

Sprite Dimensions

上述で実行したオプション。
CSS に画像の Width と Height を加えてくれます。

$<map>-sprite-dimensions: true;
@import "<map>/*.png";

Sprite Customization | Compass Documentation

Sprite Spacing

ディフォルトではスプライト画像は余白無し(0 px)で配置されています。
これに余白を加えることができます。

$<map>-spacing: 20px;
@import "<map>/*.png";

Sprite Customization | Compass Documentation

Sprite Layouts

ディフォルトのスプライト画像は縦に画像が並びます。
このオプションで、これを変更できます。

$<map>-layout: horizontal;
@import "<map>/*.png";

Sprite layouts | Compass Documentation

Selector Control

all-<map>-sprites の代わりに、<map>-sprite($name) を利用すると、スプライト CSS を個別に出力できます。
手動でクラス名を変更したい場合に。

.<map>-h {
  @include <map>-sprite(h);
  position: absolute;
  top: 90px;
  left: 30px;
}
.<map>-h {
  background-position: 0 0;
  height: 27px;
  width: 110px;
  position: absolute;
  top: 90px;
  left: 30px;
}

この他にクラス名を変更したい場合は、@extend を利用する形式でしょうか。

.foo { @extend .menus-h; }

このあたりを利用すれば、必要な出力が得られそうです。

補遺

sprite-map

Compass のヘルパーを利用して、マジックインポートを使わずにスプライト画像を生成することもできる。

必要に応じて sprite-map で細かい制御を行う際に利用するよう。
下記の Retina 対応を含め、また確認する。

Retina 対応