SCSSやCSS3の便利な機能でおいしいドーナツをつくろう

CSS3やSCSSは、誰もが知っているような有名どころの機能ももちろん便利なのですが、
ちょっと掘ってみると「そんな表現もできるのか！」というものが見つかったりします。
この記事では、私が発見したそんな機能を使っておいしいドーナツを作りたいと思います。

## ドーナツを作る

<p class="codepen" data-height="400.43646240234375" data-default-tab="css,result" data-slug-hash="LYdbroq" data-editable="true" data-user="mhousetree" style="height: 400.43646240234375px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mhousetree/pen/LYdbroq">
  doughnut</a> by mhousetree (<a href="https://codepen.io/mhousetree">@mhousetree</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

ドーナツ型の図形を作りました。これは、円の上に背景色の円を乗せているのではなく、
円の中心部分だけを`mask-image`(CSS3)で透明にすることで実現しています。

mask-imageプロパティは、値として要素のマスクレイヤーとなる画像を指定することで、要素をマスクすることができます。
画像は、いわゆる画像ファイルをurlで指定することもできますし、`linear-gradient`などを使ってグラデーションを作成してマスクをかけることもできます。
今回は、`radial-gradient`で、透明から黒へと変わる幅が0の円形グラデーション(円に見えます)を作成し、ドーナツの穴を実現しています。

さらに、外側の丸みについても、よくある`border-radius`での実装ではなく、`clip-path`で実装しています。
これは全然新しいというわけではないので、ご存知の方は多いのかもしれませんが、私は最近まで知りませんでした…！
円形やSVGなどの形状で要素をクリッピングすることができます。
今回のような、幅も高さも要素そのままの円形クリッピングの場合は正直`border-radius`で十分ですが、知っておくと役に立つ場面はあると思います！

## トッピングをのせる

<p class="codepen" data-height="400.61248779296875" data-default-tab="css,result" data-slug-hash="abYBKGY" data-editable="true" data-user="mhousetree" style="height: 400.61248779296875px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mhousetree/pen/abYBKGY">
  Untitled</a> by mhousetree (<a href="https://codepen.io/mhousetree">@mhousetree</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

ドーナツができたので、さらにおいしくトッピングしていきましょう。
今回はカラフルなカラースプレーを乗せていきたいと思います。

カラースプレーはたくさんあるので、1つ1つをスタイリングするのは大変です。
そこで、SCSSの`@for`文と、`random`関数を使って一括で記述してしまいましょう。
トッピングのスタイリング部分を抜粋すると以下の通りです。

```scss
.topping {
  position: absolute;
  width: 10px;
  height: 40px;
  border-radius: 5px;
  @for $i from 1 through 30 {
    &:nth-child(#{$i}) {
      top: #{random($size)}px;
      left: #{random($size)}px;
      transform: rotate(#{random(180)}deg);
      background-color: hsl(random(360), 90%, 90%);
    }
  }
}
```

`.topping`直下に記述したスタイルは全てのカラースプレーに共通した部分です。

`@for`の行はSCSSのfor文で、`$i`という変数を作成し、1から30までインクリメントしながら繰り返すという指示になっています。
`1 through 30`の部分について、`1 to 30`とも書けるのですが、こう書くと1から29までになってしまうので注意です。

For文の中、`nth-child`擬似クラスの装飾については、これもSCSSの機能である`random`関数がたくさん使われています。
`random`関数は、引数を指定しないと0から1までの値を、第一引数を指定すると1から指定の数までの値を返します。
`top`, `left`では、ドーナツの大きさ(直径)として定義している`$size`の値を使って、トッピングの位置をランダムに決定しています。
変数は、プロパティの値としてそのまま利用するときは`$i`のようにそのまま書けますが、今回のように値の一部として使うような場合、インターポレーション（`#{$変数名}`）の形で参照する必要があります。
`transform: rotate`では、1~180度の範囲でトッピングをランダムに傾けています。今回は点対称な図形なので回転の範囲を180度までにしました。
`background-color`では、CSS3から追加された`hsl`関数でトッピングの色を指定しています。今回のようにランダムな色を設定したいときは、`hsl`関数の第一引数`hue`に`random`関数を使うと非常に簡単に実装できます。
完全にランダムな色だけでなく、青緑〜紺色ぐらいにしたい！みたいなときにも下のように使えるので便利だと思います！

<p class="codepen" data-height="351.30462646484375" data-default-tab="css,result" data-slug-hash="oNqYMoN" data-editable="true" data-user="mhousetree" style="height: 351.30462646484375px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/mhousetree/pen/oNqYMoN">
  Untitled</a> by mhousetree (<a href="https://codepen.io/mhousetree">@mhousetree</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

CSSを簡潔に書いて、おいしいドーナツを作ることができました！
すぐ何かに役立つというわけではないかもしれませんが、不意に活用できる場面があればぜひ使ってみてください。