[決定版]Retina対応したスプライト画像のmixin

  • あとで読みたい人は…
 [決定版]Retina対応したスプライト画像のmixin

こんにちは、@cappeeです。関東も大雪でしたね(・∀・)

現在がりがりっとスマートフォンサイトのコーディングに勤しんでいます。

以前Sass+Compassを使った泣くほど早いmixin集を公開しましたが、スマホだとRetina対応があるためSprite画像を使ったmixinは変更する必要があります。

色々とRetina対応したmixinの記事を拝見させていただきましたが、background-sizeを毎回手動で入力する必要があったりと以外と「これだっ!」と思うmixinがなく。。

Compassの公式サイトや色んな角度から検索して参考にした結果、個人的には「これが決定版だ!」と思えるmixinができました!!!

CSS Spriteの設定

※こちらはCompassのスプライト初心者向けですのでわかる方はスルーしてください!

スプライト画像を使ったCSSの指定には主に以下の3つがあると思います。

  1. 文字の背景で表示する画像
  2. 文字を置換する画像
  3. アイコンの画像(文字の左側に配置)

私は(1)文字の背景で表示する画像と(2)文字を置換する画像を「replace」フォルダに書き出し、(3)アイコンの画像を「icon」フォルダに書き出しています。フォルダ名は任意です!

何はともあれCSS Spriteにしたい画像をそれぞれ書き出します。

書き出したらSass(SCSS)ファイルにスプライト画像を生成してくれる魔法の言葉を書き出します。

(1)(2)はスプライト画像のレイアウトを「$layout: smart」にして余白なく画像を配置するように指定します。
なぜなら画像サイズが大きくなりすぎるとiOSで表示の制限がかかるからです。
3メガピクセル以上の画像は縮小されて表示されるので気をつけましょう。
ただし、「$layout: smart」にするとブラウザでサイトを縮小して見た場合に隣の画像が1px見えてしまうこともあります。
画像サイズの制限に気をつけつつ、デフォルトの縦方向に並べる「vertical」で「$spacing:10px」と指定する方が無難かも?

$replace: sprite-map("sp/replace/*.png", $layout: smart);
$replace-img: sprite-url($replace);

(3)アイコンの画像は上下にある程度の余白が必要なため、「$spacing:100px」などある程度のスペースを指定しておきます。

$icon: sprite-map("sp/icon/*.png", $spacing:100px);
$icon-img: sprite-url($icon);

マジックインポートというCSSスプライト用の画像だけでなくbackground,background-positionを自動で出力してくれる機能もあります。実際はbackground-position,width,heightなど変更したい場合が多いので sprite-map を使ってセレクタごとに指定します。

Retina対応mixin

(1)文字の背景で表示するスプライト画像

@mixin sprite-background($name) {
  width: image-width(sprite-file($replace, $name)) / 2;
  height: image-height(sprite-file($replace, $name)) / 2;
  $xpos: round(nth(sprite-position($replace, $name), 1) / 2);
  $ypos: round(nth(sprite-position($replace, $name), 2) / 2);
  background-image: $replace-img;
  background-position: $xpos $ypos;
  background-repeat:no-repeat;
  $wbgz: image-width(sprite-path($replace)) / 2;
  @include background-size($wbgz auto);
}

width: image-width(sprite-file($replace, $name)) / 2;
Retina用に書きだした画像の横幅を取得して半分のサイズを出力します。heightも同じくです。

$xpos: round(nth(sprite-position($replace, $name), 1) / 2);
スプライト画像のポジションを取得して変数にいれます。
nthでポジションの何番目を取得するかを指定します。1はX軸、2はY軸です。
round関数を指定しておくと割算ででた小数点以下を四捨五入してくれます。

$wbgz: image-width(sprite-path($replace)) / 2;
background-size用にスプライト画像全体の横幅を取得し、半分のサイズを変数にいれます。

以下のように任意のセレクタでincludeして使ってください。

.selector {
  @include sprite-background(filename);
}

(2)文字を置換する画像

@mixin sprite-replace($name) {
  @include sprite-background($name);
  text-indent: 100%;
  white-space: nowrap;
  overflow: hidden;
}

上の(1)をまるっとincludeして、文字を隠すプロパティだけ指定すればOKです。

(3)アイコンの画像

@mixin sprite-icon($name, $x: 0, $y: 0, $pl: 4) {
  $xpos: round(nth(sprite-position($icon, $name), 1) / 2);
  $ypos: round(nth(sprite-position($icon, $name), 2) / 2);
  background-position: ($xpos + $x) ($ypos + $y);
  $wbgz: image-width(sprite-path($icon)) / 2;
  @include background-size($wbgz auto);
  padding-left: (image-width(sprite-file($icon, $name)) / 2) + $pl;
}

background-position: ($xpos + $x) ($ypos + $y);
上と同じく画像のポジションを取得して変数にいれた後、位置を微調整できるようにしておきます。
アイコン画像は特にY軸を調整したい時が多いのでこの指定は必須ですね。

padding-left: (image-width(sprite-file($icon, $name)) / 2) + $pl;
アイコン左側のpadding-leftも自動で計算します。
デフォルトはアイコン画像の幅の半分に、4px分プラスして出力されます。
ただデザインによっては調整したい場合もあるので手動でもpadding-leftを指定できるようにしています。includeした際に$plが指定されていれば、指定されたpxが出力します。
[追記]px数もアイコンごとに調整できるように変更しました!

以下のように任意のセレクタでincludeして使ってください。
アイコンはclass名を「icon-xx」と先頭部分を共通化し、属性セレクタでスプライト画像のパスを指定すると便利です。
class名を共通化できない場合は、下記で記述したようにextend化してmixinにしてもOKです。

[class*="icon-"]{
  background-image: $icon-img;
  background-repeat: no-repeat;
}
.icon-home {
  @include sprite-icon(home);
}
.icon-li {
  @include sprite-icon(li, 0, 2, 6);
}

extend

(1)(2)で指定した以下の共通プロパティはextend化して、複数のセレクタでプロパティをまとめて指定することもできます。

extend

%sprite-background {
  background-image: $replace-img;
  background-repeat:no-repeat;
}
%sprite-replace {
  text-indent: 100%;
  white-space: nowrap;
  overflow: hidden;
}

(1)文字の背景で表示するスプライト画像のmixin

@mixin sprite-background($name) {
  @extend %sprite-background;
  width: image-width(sprite-file($replace, $name)) / 2;
  height: image-height(sprite-file($replace, $name)) / 2;
  $xpos: round(nth(sprite-position($replace, $name), 1) / 2);
  $ypos: round(nth(sprite-position($replace, $name), 2) / 2);
  background-position: $xpos $ypos;
  $wbgz: image-width(sprite-path($replace)) / 2;
  @include background-size($wbgz auto);
}

(2)文字を置換する画像のmixin

@mixin sprite-replace($name) {
  @include sprite-background($name);
  @extend %sprite-replace;
}

extendを使うとどうしてもセレクタの数が増えてしまいます。IE9以下では1つのCSSファイルにつき4,095個までしかセレクタを認識しないという制限がありますので気をつけましょう。

いかがでしたでしょうか?
このmixinでスマホサイトのコーディングが少しでも早くなれば嬉しいです!

間違いやもっと良い方法があるという方はお気軽にコメントください。

上記以外のmixinはこちらにもまとまってます(*´ω`*)
Sass+Compassを使った泣くほど早いmixin集

Sassの教科書も必読ですよ。

Pocket
article clipper [決定版]Retina対応したスプライト画像のmixin

One thought on “[決定版]Retina対応したスプライト画像のmixin

  1. $replace: sprite-map(“sp/replace/*.png”… の記述で
    “/*”がCSSコメントアウトとしてDreamweaverに認識されてしまい、
    koalaでエラーこそ出ないものの、スプライト画像が生成されなくなってしまいました。。

コメントを残す

メールアドレスが公開されることはありません。

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>