Compassを使ったSpriting最適化 [Retina編]


前回、[CompassのSpriteが進化していた](http://qiita.com/soheikitada/items/578a277c77273468db8b)で、今まで知らなかったCompassのSpriting関連の関数をキャッチアップしましたが、今どきの実用面ではRetinaディスプレイのサポートをする必要があります。

そこでこのようにコーディングします。

## ディレクトリ構成

Compassのconfigで指定した画像フォルダに、

```
icons_1x
├ icon-facebook.png
├ icon-twitter.png
└ icon-github.png

icons_2x
├ icon-facebook.png
├ icon-twitter.png
└ icon-github.png
```

という風に1x画像、2x画像を分けて入れる。

## mixinの定義

```scss
@import "compass";
@import "compass/utilities/sprites";

// スプライト画像の読み込み
$icons_1x-sprites: sprite-map( 'icons_1x/*.png', $spacing: 2px );
$icons_2x-sprites: sprite-map( 'icons_2x/*.png', $spacing: 4px );

@mixin get-icons-sprite( $sprite, $retina: false ) {
  $map-url: sprite-url( $icons_1x-sprites );
  $sprite-position: sprite-position( $icons_1x-sprites, $sprite );
  background: $map-url $sprite-position no-repeat;

  $sprite-image: sprite-file( $icons_1x-sprites, $sprite );
  width: image-width( $sprite-image );
  height: image-height( $sprite-image );

  @if $retina == true {
    @include media-retina {
      background-image: sprite-url( $icons_2x-sprites );
      background-size: image-width( sprite-path( $icons_1x-sprites ) ) auto;
    }
  }
}
```


## 使用例


```scss
$icon-names: (
              'icon-facebook'
              'icon-twitter'
              'icon-github'
              );

@each $icon-name in $icon-names {
  .icons-#{ $icon-name } {
    display: inline-block;
    @include get-icons-sprite( #{ $icon-name }, true );
  }
}
```

```html
<i class="icons-icon-facebook"></i>
<i class="icons-icon-twitter"></i>
<i class="icons-icon-github"></i>
```

生成されたCSSは以下。

```css
.icons-icon-facebook {
  display: inline-block;
  background: url('../../assets/images/icons_1x-s3241a4cef7.png') 0 0 no-repeat;
  width: 48px;
  height: 48px; }
  @media only screen and (min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3 / 2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
    .icons-icon-facebook {
      background-image: url('../../assets/images/icons_2x-sda4f458d0f.png');
      background-size: 48px auto; } }

.icons-icon-twitter {
  display: inline-block;
  background: url('../../assets/images/icons_1x-s3241a4cef7.png') 0 -100px no-repeat;
  width: 48px;
  height: 48px; }
  @media only screen and (min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3 / 2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
    .icons-icon-twitter {
      background-image: url('../../assets/images/icons_2x-sda4f458d0f.png');
      background-size: 48px auto; } }

.icons-icon-github {
  display: inline-block;
  background: url('../../assets/images/icons_1x-s3241a4cef7.png') 0 -50px no-repeat;
  width: 48px;
  height: 48px; }
  @media only screen and (min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3 / 2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
    .icons-icon-github {
      background-image: url('../../assets/images/icons_2x-sda4f458d0f.png');
      background-size: 48px auto; } }
```

## import を使う場合

mixinを定義する際に、最初の2行で、 `sprite-map` という関数をコールして、見えない変数がCompassによって自動的に定義されるのを避けましたが、Compassのimport機能を使って、

```sprite-mapを使わない例
$icons_1x-spacing: 2px;
@import "icons_1x/*.png";
// → $icons_1x-sprites が定義される

$icons_2x-spacing: 4px;
@import "icons_2x/*.png";
// → $icons_2x-sprites が定義される
```

という書き方をしても、同じ結果が得られます。

## Retinaディスプレイの条件分岐

[Retinaディスプレイを分岐するmixin](http://qiita.com/soheikitada/items/bc71997c6f1be6ba9b4d) で紹介したmixin「`media-retina`」を利用していますが、 [Modernizr](https://github.com/modernizr/modernizr) などを使っても良いでしょう。

```scss
@mixin media-retina() {
  @media only screen and (min-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-device-pixel-ratio: 1.5) {
    @content;
  }
}
```


## 参考

- [Using Compass Generated Sprite Sheets in Responsive Sass, by Jayson Jacobs.](http://www.hugeinc.com/ideas/perspective/using-compass-generated-sprite-sheets-in-responsive-sass)