spritesmithでCSSスプライト画像を合成し、CSSも出力することができますが、iOS retina対応にはなりません。
各画像は@2xで合成し、CSSの各座標情報は1/2としたいのですが、そのようなオプションはないようです。
そこで、spritesmithの出力形式にstylusを指定し、このstylusファイルを読み込んで、1/2された各画像のCSSを出力するstylusのfunctionを書くことにしました。
環境
- node.js v0.10.26
- grunt-cli v0.1.13
- grunt v0.4.4
- grunt-contrib-stylus 0.14.0
- grunt-spritesmith 1.24.0
gruntからspritesmithを実行
Gruntfileに以下のようなタスクを記述します。
sprite: { icons: { src: '<%= dir.src %>/assets/sprites/*.png', destImg: '<%= dir.src %>/assets/img/sprite.png', destCSS: '<%= dir.src %>/assets/css/sprite.styl', algorithm: 'left-right', cssFormat: 'stylus', cssOpts: { function: false } } },
これを実行すると、作成されたsprite.png上の座標情報がstylusの変数として出力されます。以下のものが、スプライトの一つの画像の情報です。実際は全ての画像の変数が出力されます。cssOptsのfunctionをtrueにしておくと、必要なファンクションも出力します。今回はfalseとしますが、サンプルとして下記に掲載します。
$icn-home_x = 222px; $icn-home_y = 0px; $icn-home_offset_x = -222px; $icn-home_offset_y = 0px; $icn-home_width = 44px; $icn-home_height = 44px; $icn-home_total_width = 916px; $icn-home_total_height = 86px; $icn-home_image = '../img/fw-sprite.png'; $icn-home = 222px 0px -222px 0px 44px 44px 916px 86px '../img/sprite.png'; spriteWidth($sprite) { width: $sprite[4]; } spriteHeight($sprite) { height: $sprite[5]; } spritePosition($sprite) { background-position: $sprite[2] $sprite[3]; } spriteImage($sprite) { background-image: url($sprite[8]); } sprite($sprite) { spriteImage($sprite) spritePosition($sprite) spriteWidth($sprite) spriteHeight($sprite) }
出力CSS
上記の情報を元に、以下のようなCSSを出力することを考えます。
positionやwidth,heightを1/2にしています。出力されるファンクションでは1/2する機能がないので、修正が必要ですが、全て自分で書くのも簡単です。
.icon-home { background: url("../img/sprite.png") no-repeat -111px 0px; width: 22px; height: 22px; -webkit-background-size: 458px 43px; background-size: 458px 43px; }
stylusのファンクション
独自のsprite()関数に、上記の変数である$icn_homeを渡して、CSSを出力します。
retina()関数は、座標や大きさを1/2にする関数です。値に’px’が付加されているせいか、直接1/2することができませんでしたので、別の関数にしました。operate(‘/’, a, b)としてbuildin functionを呼び出してもよいです。
/* * 各スプライトの位置と大きさを読み込む。 */ @import 'sprite.styl' /* * 座標、大きさを1/2する。 */ retina($x) $x / 2 /* * スプライト画像の座標、大きさから、CSSを出力する。 */ sprite($args) background url($args[8]) no-repeat retina($args[2]) retina($args[3]) width retina($args[4]) height retina($args[5]) background-size retina($args[6]) retina($args[7]) /* * .icn_homeクラスを出力する。sprite()をmixinで呼び出す。 */ .icn_home sprinte($icn_home)
これで、目的のCSSを得ることができました。stylusは構文がシンプルかつ自由で、非常に導入しやすいCSSプリプロセッサです。LessやSass以外の選択肢としても、最適です。