CSSのgradient指定について知っておいたらドヤ顏できる（かもしれない）５つのこと

## CSSのグラデーション指定、どうしてますか？

Photoshopなどでオブジェクトのグラデーションが指定してあったら `CSSをコピー` という機能でそのままCSSが生成できたり、 [Ultimate CSS Gradient Generator](http://www.colorzilla.com/gradient-editor/) みたいなサイトでCSSを生成させてそれを貼り付けたりする方法もありますが、できれば理屈や理論をある程度理解したうえで使いこなしてみたいものです。

意外と知らないことが多かったり、「なんとなく思った通りになった」程度で止まっている人も少なくはないのではないかと思いますので、おさらいも兼ねて見てみましょう。

## 1. gradient指定の理屈を知ろう

1: **gradient**指定には以下の４種類があります。

* 線形グラデーション `linear-gradient()`
* 円形グラデーション `radial-gradient()`
* 反復線形グラデーション `repeating-linear-gradient()`
* 反復円形グラデーション `repeating-radial-gradient()`

*[CSS Gradient Comparison](https://codepen.io/kyoyababa/pen/rjwgqY)*
![Screen Shot 2017-01-25 at 12.01.42 AM.png](https://qiita-image-store.s3.amazonaws.com/0/105252/28273e80-fe84-f98a-871a-a13ad2da37d7.png)

2: 丸括弧内の引数は３種類あります。

* **size**（サイズ定数。`linear-`系では使いません。詳細は後述）
* **angle**（角度）
* **color / color-stop**（構成カラーとカラーストップ、つまりカラーの区切り位置）

3: **angle**は省略可能で、defaultは `0deg == top == to bottom` となります。旧仕様（？）では開始位置を `top` `left` のように記述していましたが、W3Cの勧告や多くの新しいブラウザでは `to bottom` `to right` のように到着地点を `to xxx` 型で示し開始位置を暗黙に示すのがルールになっています。[^deg指定の方法]

[^deg指定の方法]: `deg` 指定と `to bottom` `to right` 型のどちらを適用すればよいのかは、コーディングガイドラインとして各自が定めればよいと思います。これは、たとえば `background-position` を `50%` と指定するのか `center` と指定するのかという点と同様です。

4: **color**は最低ひとつ必要で、任意のカラーリテラル・hex値・rgb(rgba)値・hsl(hsla)値が使えます。

5: **color-stop**は省略可能で、省略した場合は0% ~ 100%間でよしなにブラウザが調整してくれます。任意の値は、px値や%などあらゆる単位が利用可能です。

6: 旧世代のブラウザでは `-webkit- / -moz- / -o-` のプレフィックスが必要になり、 `to xxx` 型の角度指定シンタックスが通用しない場合があります[^フォールバック]。以下の [Can I use...](http://caniuse.com/#search=gradient) の右上が黄色くなっているところがプレフィックスが必要なブラウザバージョンです。

*[Can I use... - gradient](http://caniuse.com/#search=gradient)*
<img width="1261" alt="Screen Shot 2017-01-24 at 午後7.57.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/105252/97887626-33d9-4d27-8ac5-5b2eebf1848f.png">

7: IE9以下では `xxx-gradient()` 自体が通用しないので、 `filter` プロパティを使用して `progid:DXImageTransform.Microsoft.gradient()` というめんどくさいことを書かなければいけませんが、IE9以下でグラデーションが付与されなくて情報設計に影響が出る例なんて存在しないと思っているので、せいぜいフォールバックがあれば問題ないでしょう。[^フォールバック]

[^フォールバック]: `-webkit-gradient(linear, ...)` という記述方式も一時期あった気がしますが、たぶん無かったことにして大丈夫です。なお、念のため補足するとIE5以下のようにグラデーションレンダリングそのものができないブラウザもあり、そのブラウザに対応する場合はフォールバックとして `background-color` を指定しておくのが慣習となっています。ただし、transparencyなgradientと重複させると `background-color` が見えてしまうので気を付けましょう。

## 2. **color / color-stop**の指定を自在に操るために

前述の通り、カラー指定にはカラーとカラーストップが併記され、カラーストップは省略可能で、ブラウザがよしなに調整してくれます。たとえば以下のように。

```CSS:ブラウザがよしなに分配してくれる例
background-image: linear-gradient(to right, red, green, yellow);
```

![Screen Shot 2017-01-25 at 12.04.08 AM.png](https://qiita-image-store.s3.amazonaws.com/0/105252/80967ec8-d3b6-5094-f089-48f333095dce.png)

```CSS:明示的に割合を指定する場合
background-image: linear-gradient(to right, red 50%, green 60%, yellow 70%);
```

![Screen Shot 2017-01-25 at 12.08.40 AM.png](https://qiita-image-store.s3.amazonaws.com/0/105252/9925a2e8-ca80-c155-f2ce-6e3819f86e67.png)

```CSS:場合によっては、領域をはみ出させる指定も可能
background-image: linear-gradient(to right, red 10%, green 150%);
```

![Screen Shot 2017-01-25 at 12.08.46 AM.png](https://qiita-image-store.s3.amazonaws.com/0/105252/169f6cf4-c088-8678-c55f-c9d5d4f8c3bf.png)

## 3. 透明 (transparent) を扱うときは気をつけよう

`transparent` 値を使うときは、ブラウザによって表示結果が異なることに注意が必要だ。

```CSS:transparentを含むグラーデーションを作ってみる
background-color: red;
background-image: linear-gradient(to right, transparent, white);
```

ChromeやFirefoxなどでは、以下のように表示されます。

![Screen Shot 2017-01-25 at 12.18.15 AM.png](https://qiita-image-store.s3.amazonaws.com/0/105252/b026dbc9-fb1f-2af2-24a8-8999ff8444d2.png)

上記は想定の範囲内だが、（一部の）FirefoxやSafariでは以下のように表示されてしまう！[^browser-bug]

[^browser-bug]: めんどくさいのでバージョンは調べていませんが、過去にそれで失敗したことがありました。

![Screen Shot 2017-01-25 at 1.00.17 AM.png](https://qiita-image-store.s3.amazonaws.com/0/105252/6f41a4ce-c5ed-0231-9c18-fd9ccb9beaf5.png)

これは、**`transparent == rgba(0,0,0,0)`である**というカラーリテラルの仕様を、FirefoxやSafariが**忠実に踏襲してしまった**ことが原因である（だから、仕様的には実はこちらが正しいのである）。グラーデーションを指定するときは、ベースとなるカラーが必ずあるはずだから、たとえば`#FFFFFF`なら`rgba(255,255,255,0)`とちゃんと書く癖をつけよう。[^polyfill]

[^polyfill]: SassやScssを使っているなら`rgba(#FFFFFF, 0.x)`と書いてもちゃんとRGB値に変換して出力するから、変数の管理も楽になります。しかし、minifyのプラグインが`transparent`値に変換してしまう場合もあるので注意が必要です。

## 4. radialのsize

`radial-gradient()` `repeating-radial-gradient()` にはサイズ定数があります。

* `ellipsis`（デフォルト値）
* `closest-corner`
* `closest-side`
* `farthest-corner`
* `farthest-side`
* 任意の数値

これについては言葉で説明するより図での紹介が手っ取り早いので、以下の画像に役を譲ります。

![Screen Shot 2017-01-25 at 12.36.34 AM.png](https://qiita-image-store.s3.amazonaws.com/0/105252/ffd056be-076a-bb50-004f-2c24dc75a682.png)

次の章「background-xxxプロパティとの連携」で述べるように、これらのradial-gradientはellipsisだけで再現することが可能で、実はサイズ定数は要らない子かもしれません。

## 5. `background-xxx`プロパティとの連携

`background-image`プロパティで描画している以上、背景としてレンダリングされるので、あらゆる`background-xxx`プロパティとの連携が可能です。

```CSS:background-sizeによる拡大・縮小
background-size: 50px 50px;
```

![Screen Shot 2017-01-25 at 12.57.38 AM.png](https://qiita-image-store.s3.amazonaws.com/0/105252/dbea6ca7-a5ce-9bab-6ae3-36c31bd5bf33.png)

ポジションの移動も、`background-image` なので同様に可能です。

```CSS:background-positionによる移動
background-size: 50px 50px;
background-position: 50% 50%;
```

![Screen Shot 2017-01-25 at 12.57.44 AM.png](https://qiita-image-store.s3.amazonaws.com/0/105252/2ef68306-6d93-2b91-f711-f180019922e7.png)

`background-repeat` を併用することももちろん可能ですが、反復線形グラデーション `repeating-linear-gradient()` や、反復円形グラデーション `repeating-radial-gradient()` という専用の値も用意されているので、どちらを使うかはコーディングルールとして一貫性を保てればよいでしょう。

```CSS:background-repeatによる繰り返し
background-size: 50px 50px;
background-repeat: repeat-y;
```

![Screen Shot 2017-01-25 at 12.57.49 AM.png](https://qiita-image-store.s3.amazonaws.com/0/105252/61546d29-fc1e-610a-d3bc-8a8aa8169b82.png)

## 5. 複雑なグラデーションの実装を求められたときは

上記のようにいろいろな手法を説明してきたが、これらはあくまでも仕様とロジックについての解説であり、ケーススタディではありません。gradientの値を使うことで、表現技法として**照明が当たっているような演出**をしたり、**縞模様やチェック柄**のようなパターンをネイティブCSSで実装することも可能ですが、実運用では**デザイナーがそのデザインをPhotoshopで仕上げている**はずなので、やはり**CSSをコピー**したり、**そもそもSVGを使う**といったことも検討することを忘れてはならないでしょう。