LoginSignup
3
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2015-12-06

前回、CompassのSpriteが進化していたで、今まで知らなかった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の定義

@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;
    }
  }
}

使用例

$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 );
  }
}
<i class="icons-icon-facebook"></i>
<i class="icons-icon-twitter"></i>
<i class="icons-icon-github"></i>

生成された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機能を使って、

$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 で紹介したmixin「media-retina」を利用していますが、 Modernizr などを使っても良いでしょう。

@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;
  }
}

参考

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2