Cloudinaryにアップロードした画像でCSS Spriteをやってみる

マニュアルをぱらぱらと見ていたらCloudinaryでCSS Spriteをサポートしているということで、試しにやってみました。手軽過ぎてびびる

#使ったもの
いらすとやさんから借りてきた画像
![](https://res.cloudinary.com/kanaxx/t_qiita_thumb/capital_a.png) ![](https://res.cloudinary.com/kanaxx/t_qiita_thumb/capital_b.png) ![](https://res.cloudinary.com/kanaxx/t_qiita_thumb/capital_c.png) ![](https://res.cloudinary.com/kanaxx/t_qiita_thumb/capital_d.png) ![](https://res.cloudinary.com/kanaxx/t_qiita_thumb/capital_e.png)

#手順
##画像をアップロード
Media Libraryを使って画像をアップロードします。
public_idは、capital_a, capital_b, capital_c, capital_d, capital_eのままにしてあります。

##画像にタグをつける
CSS Spriteする画像にTagを付けます。Tagがついているもので判別するのでタグ付け大事です。
A、Eには、```capital```と```vowel```のタグを付け
![](https://res.cloudinary.com/kanaxx/t_border_gray/qiita/2018-12-09_17h04_12.png)

B、C、Dには、```capital```と```consonant```のタグを付けます
![](https://res.cloudinary.com/kanaxx/t_border_gray/qiita/2018-12-09_17h04_39.png)


##画像の結合
タグ付けした画像は、このようなURLで1枚の画像として取得できます。URLに含まれるimage/spriteは固定で、最後の部分はタグ名.画像形式(拡張子)にします。

■**ABCDEを5枚を結合するURL**（231x1158, 219 KB PNG）
最後の部分が```capital```なので、capitalタグをつけたABCDEの5枚の画像が対象です。クリックするとわかりますが、縦につながった1枚の画像が自動で作られます。
https://res.cloudinary.com/kanaxx/image/sprite/capital.png
![](https://res.cloudinary.com/kanaxx/image/sprite/capital.png)

■**ABCDEをくっ付けた1枚の画像をwのパラメータで小さくする**（50x258, 17.7 KB PNG）
Cloudinaryなので、パラメータで画像のサイズの変更もできます。上の画像を幅50pxにするには、URLにw_50を挟むだけです。
https://res.cloudinary.com/kanaxx/image/sprite/w_50/capital.png
![](https://res.cloudinary.com/kanaxx/image/sprite/w_50/capital.png)

■**母音(vowel)だけ取り出す**
最後の部分を```vowel```に変えるだけで、vowelタグが付いているAとEの画像が取り出せます。
[https://res.cloudinary.com/kanaxx/image/sprite/w_50/**vowel**.png](https://res.cloudinary.com/kanaxx/image/sprite/w_50/vowel.png)
![](https://res.cloudinary.com/kanaxx/image/sprite/w_50/vowel.png)

もちろん、子音もできます。
[https://res.cloudinary.com/kanaxx/image/sprite/w_50/**consonant**.png](https://res.cloudinary.com/kanaxx/image/sprite/w_50/consonant.png)
![](https://res.cloudinary.com/kanaxx/image/sprite/w_50/consonant.png)



##画像を切り出すCSSを作る
CloudinryのCSS Spriteを使うと画像を結合だけではなくCSSも一緒に作ってくれます。世間的には、このCSSのピクセル調整作業が面倒らしいですが、Cloudinaryなら自動で作れます。CSSの取り出し方は画像のURLの拡張子部分をCSSに変えるだけです。

■**ABCDEのCSS**
https://res.cloudinary.com/kanaxx/image/sprite/capital.css

```css:capital.css
>.capital_a, .capital_b, .capital_c, .capital_d, .capital_e {
  background: url('//res.cloudinary.com/kanaxx/image/sprite/v1544339487/capital.png') no-repeat;
}
.capital_a { background-position: 0px 0px; width: 231px; height: 230px; }
.capital_b { background-position: 0px -232px; width: 231px; height: 230px; }
.capital_c { background-position: 0px -464px; width: 231px; height: 230px; }
.capital_d { background-position: 0px -696px; width: 231px; height: 230px; }
.capital_e { background-position: 0px -928px; width: 231px; height: 230px; }
```

■**幅を50pxにしたCSS**
当然、位置調整をしたCSSが戻ってきます。
https://res.cloudinary.com/kanaxx/image/sprite/w_50/capital.css


```css:capital.css(w_50)
.capital_a, .capital_b, .capital_c, .capital_d, .capital_e {
  background: url('//res.cloudinary.com/kanaxx/image/sprite/w_50/v1544339574/capital.png') no-repeat;
}
.capital_a { background-position: 0px 0px; width: 50px; height: 50px; }
.capital_b { background-position: 0px -52px; width: 50px; height: 50px; }
.capital_c { background-position: 0px -104px; width: 50px; height: 50px; }
.capital_d { background-position: 0px -156px; width: 50px; height: 50px; }
.capital_e { background-position: 0px -208px; width: 50px; height: 50px; }
```


CSS内のpublic_idが被ることも想定されていて、CSS内のクラスに付けるPrefixを指定することもできます。URLの一部に```p_(プレフィックス名)```を付けるだけです。pの後ろのアンスコは区切り文字なのでつきません。S_がプリフィックスです。出力されるCSSのすべてのクラスの先頭に```S_```が付きます。
[https\://res.cloudinary.com/kanaxx/image/sprite/w_50/**p_S_**/capital.css](https://res.cloudinary.com/kanaxx/image/sprite/w_50/p_S_/capital.css)


```css

.S_capital_a, .S_capital_b, .S_capital_c, .S_capital_d, .S_capital_e {
  background: url('//res.cloudinary.com/kanaxx/image/sprite/w_50/p_S_/v1544345252/capital.png') no-repeat;
}
.S_capital_a { background-position: 0px 0px; width: 50px; height: 50px; }
.S_capital_b { background-position: 0px -52px; width: 50px; height: 50px; }
.S_capital_c { background-position: 0px -104px; width: 50px; height: 50px; }
.S_capital_d { background-position: 0px -156px; width: 50px; height: 50px; }
.S_capital_e { background-position: 0px -208px; width: 50px; height: 50px; }
```


##HTMLに当て込む
HTML側でやることは、Cloudinaryから出力されるCSSのURLを取り込み、画像を表示したい要素にclass=public_idを付けるだけです。画像をくっつけるコードもCSSも全く書く必要なし。とっても簡単ですね！

```html
<html>
    <head>
        <title>CSS Sprite Sample with Cloudinary</title>
        <link href="https://res.cloudinary.com/kanaxx/image/sprite/capital.css" 
        media="screen" rel="stylesheet" type="text/css" />

        <link href="https://res.cloudinary.com/kanaxx/image/sprite/w_50/p_S_/capital.css" 
        media="screen" rel="stylesheet" type="text/css" />

        <meta charset="utf-8"/>

    </head>
    <body>
        <h1>CSS Sprite sample</h1>

        <div class='capital_a'></div>
        <div class='S_capital_a'></div>

        <div class='capital_b'></div>
        <div class='S_capital_b'></div>

        <div class='capital_c'></div>
        <div class='S_capital_c'></div>

        <div class='capital_d'></div>
        <div class='S_capital_d'></div>

        <div class='capital_e'></div>
        <div class='S_capital_e'></div>

    </body>
</html>
```

HTMLはここに置いておきます
https://kanaxx.github.io/cloudinary/css-sprite.html


#マウスオーバーで画像を切り替えできるCSS Sprite
複数の画像を結合してCSSで切り出せることは分かったので、マウスを乗せたときに画像が切り替わるように作ってみます。CSSだけで画像の位置を切り替えるには、```:hover```疑似クラスを使えばよさそうです[^1]。Cloudinaryに自動生成されるCSSに:hoverを入れ込む方法を考えます。
[^1]: CSSスプライトで画像を円滑に表示させる https://www.webcreatorbox.com/tech/css-sprite

##画像の用意
マウスが乗ったときに表示する画像と、離れたときに表示する画像を用意します。全く同じサイズの色違い画像にします。
![](https://res.cloudinary.com/kanaxx/number_1.png)![](https://res.cloudinary.com/kanaxx/number_1:hover.png)

自動生成されるCSSのクラス名がpublic_idになるので、マウスが乗ったときに見せる画像のpublic_id(画像名)を```:hover```を付けます。今回の例は、元の画像が```number_1```という画像なので```number_1:hover```という名前に変更します。

![](https://res.cloudinary.com/kanaxx/qiita/2018-12-10_22h48_42.png)

この先の手順は今までと同じです。何かしら画像にタグをつけてCSSを取り出してみます。
https://res.cloudinary.com/kanaxx/image/sprite/sprite_mouse.css

```css:sprite_mouse.css
.number_1, .number_1:hover {
  background: url('//res.cloudinary.com/kanaxx/image/sprite/v1544450231/sprite_mouse.png') no-repeat;
}
.number_1 { background-position: 0px 0px; width: 231px; height: 230px; }
.number_1:hover { background-position: 0px -232px; width: 231px; height: 230px; }
```

うまくいっているっぽいです。

##HTMLに組み込んでみる
HTMLファイルも今までの例と変わりません。1つCSSを取り込んでdivタグにclass="number_1"を付けただけです。これだけでうまくいきました。

```html
<html>
    <head>
        <title>CSS Sprite and mouse event</title>

        <link href="https://res.cloudinary.com/kanaxx/image/sprite/spritetest.css" 
        media="screen" rel="stylesheet" type="text/css" />

        <meta charset="utf-8"/>

    </head>
    <body>
        <h1>CSS Sprite and mouse event</h1>

        <div class='number_1'></div>

    </body>
</html>
```

ここに動くものを置いてあります。
https://kanaxx.github.io/cloudinary/css-sprite-mouse.html


#おまけ　CSS Spriteの画像を最適化する
Cloudinaryは```f_auto```パラメータを使うと、Chromeならwebpフォーマット、Firefoxなら元画像のフォーマットでファイルを返すことができます。CSS Spriteでもできるか実験してみました。

最初に作ったCSS。CSSの中にあるbackgroundの画像ファイルはPNG。
https://res.cloudinary.com/kanaxx/image/sprite/capital.css

```css
.capital_a, .capital_b, .capital_c, .capital_d, .capital_e {
  background: url('//res.cloudinary.com/kanaxx/image/sprite/v1544339487/capital.png') no-repeat;
}
.capital_a { background-position: 0px 0px; width: 231px; height: 230px; }
.capital_b { background-position: 0px -232px; width: 231px; height: 230px; }
.capital_c { background-position: 0px -464px; width: 231px; height: 230px; }
.capital_d { background-position: 0px -696px; width: 231px; height: 230px; }
.capital_e { background-position: 0px -928px; width: 231px; height: 230px; }
```

f_autoパラメータを挟んだCSSパス
https://res.cloudinary.com/kanaxx/image/sprite/f_auto/capital.css

```css:chromeで見たCSSの中身
.capital_a, .capital_b, .capital_c, .capital_d, .capital_e {
  background: url('//res.cloudinary.com/kanaxx/image/sprite/f_webp,fl_awebp/v1544452632/capital.webp') no-repeat;
}
.capital_a { background-position: 0px 0px; width: 231px; height: 230px; }
.capital_b { background-position: 0px -232px; width: 231px; height: 230px; }
.capital_c { background-position: 0px -464px; width: 231px; height: 230px; }
.capital_d { background-position: 0px -696px; width: 231px; height: 230px; }
.capital_e { background-position: 0px -928px; width: 231px; height: 230px; }
```

```css:firefoxで見たCSSの中身
.capital_a, .capital_b, .capital_c, .capital_d, .capital_e {
  background: url('//res.cloudinary.com/kanaxx/image/sprite/f_auto/v1544453848/capital.png') no-repeat;
}
.capital_a { background-position: 0px 0px; width: 231px; height: 230px; }
.capital_b { background-position: 0px -232px; width: 231px; height: 230px; }
.capital_c { background-position: 0px -464px; width: 231px; height: 230px; }
.capital_d { background-position: 0px -696px; width: 231px; height: 230px; }
.capital_e { background-position: 0px -928px; width: 231px; height: 230px; }
```

同じCSSを指すURLだけど、ブラウザによってbackbroud urlが変わります。Chromeでアクセスするとlogo.webpを返し、firefoxでアクセスするとlogo.pngを返しています。


ちなみに、画像サイズはwebpが圧倒的に小さくなりました。
**219KB**　http://res.cloudinary.com/kanaxx/image/sprite/v1544339487/capital.png
**26.6KB**　http://res.cloudinary.com/kanaxx/image/sprite/f_webp,fl_awebp/v1544452632/capital.webp
**219KB**　http://res.cloudinary.com/kanaxx/image/sprite/f_auto/v1544453848/capital.png


これも、HTMLファイルを置いておきます
https://kanaxx.github.io/cloudinary/css-sprite-f_auto.html
      

#まとめ
バラバラの画像を作って、1枚につなげて、ピクセルを正確に指定したCSSファイルを作るなんて手間をかけることなく、Cloudinaryに画像をアップロードするだけでCSS Spriteができました。メンテナンスが面倒と言われがちなCSS Spriteもこんなに簡単にできるようになったんですね。

#参考資料
**Sprite generation**
https://cloudinary.com/documentation/sprite_generation

**CSSスプライトで画像を円滑に表示させる**
https://www.webcreatorbox.com/tech/css-sprite