CSSだけでコインを作ってみた

仕事で**コインモチーフ**を使ったデザインを作ることがよくあります。
普段はイラレやらフォトショやらで作っているのですが、
CSSだけで作れたらもしかして楽かも？さらに**くるくる回せたらかわいい**かも？🤔
ということでいくつかのパターンで作ってみました。

**仕事で使えるかどうかは分かりません。**

:::note warn
この記事では、ベンダープレフィックスを省略しています。
:::

# 上向きコイン

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="oNamqNQ" data-user="fbllajgh-the-encoder" style="height: 300px; 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/fbllajgh-the-encoder/pen/oNamqNQ">
  上向きコイン</a> by n-mzb (<a href="https://codepen.io/fbllajgh-the-encoder">@fbllajgh-the-encoder</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

まずはベーシックなコインです。
厳密には奥行きが表現されていなくて不自然ですが、ちょっとした装飾に使う分には悪くないかと思います。

側面は、疑似要素 `::before` を使って背面に円を配置して表現しています。
ギザギザ風の柄は `repeating-linear-gradient` で設定しました。

```css:css
background: repeating-linear-gradient(90deg, #e5c10b, #e5c10b 5px, #ffd400 5px, #ffd400 10px);
```

# 右向きコイン

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="abRXYLQ" data-user="fbllajgh-the-encoder" style="height: 300px; 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/fbllajgh-the-encoder/pen/abRXYLQ">
  右向きコイン</a> by n-mzb (<a href="https://codepen.io/fbllajgh-the-encoder">@fbllajgh-the-encoder</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

側面（用の円）の位置と柄の角度を変えれば、コインの向きを調整することができます。

```css:css
top: -5px;
left: -15px;
background: repeating-linear-gradient(-45deg, #e5c10b, #e5c10b 5px, #ffd400 5px, #ffd400 10px);
```

# 輝くコイン

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="MWPLGZN" data-user="fbllajgh-the-encoder" style="height: 300px; 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/fbllajgh-the-encoder/pen/MWPLGZN">
  輝くコイン</a> by n-mzb (<a href="https://codepen.io/fbllajgh-the-encoder">@fbllajgh-the-encoder</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

コインがキラッと輝くアニメーションを追加しました。
`linear-gradient` で設定したグラデーションの位置をアニメーションで動かしています。

```css:css
background: linear-gradient(45deg, #e5c10b 10%, #fee9a0 15%, #e5c10b 20%) top/1000px;
animation: coin_shining 15s linear infinite;
```

# グラデーションコイン

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="vYVbjBG" data-user="fbllajgh-the-encoder" style="height: 300px; 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/fbllajgh-the-encoder/pen/vYVbjBG">
  グラデーションコイン</a> by n-mzb (<a href="https://codepen.io/fbllajgh-the-encoder">@fbllajgh-the-encoder</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

少しリッチな見た目にしてみました。
`border` で作っていた縁は `transparent` で透過にして内側と同じグラデーションを適用させています。
`background` で指定している `border-box` は `background-origin` の値です。

:::note info
`background-origin` は背景画像を適用する基準位置を指定するプロパティです。
`border-box` にすることで、ボーダーの範囲にもグラデーションを適用しています。
:::

```css:css
border: 10px solid transparent;
background: linear-gradient(45deg, #b28704 20%, #ffec8c, #d9b60b 80%) border-box border-box;
```

# 回転するコイン

<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="mdzvyZK" data-user="fbllajgh-the-encoder" style="height: 300px; 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/fbllajgh-the-encoder/pen/mdzvyZK">
  回転するコイン</a> by n-mzb (<a href="https://codepen.io/fbllajgh-the-encoder">@fbllajgh-the-encoder</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

一番やりたかった**くるくる回るコイン**です。
Y軸回転させるだけならそれっぽく見えなくも…ない…？

## パーツ

- 表面
- 表面の窪み（色が暗い部分）
- 側面
- 裏面
- 裏面の窪み（色が暗い部分）

```html:html
<div class="coin">
  <div class="parts front"></div>
  <div class="parts front inner">P</div>
  <div class="parts side"></div>
  <div class="parts back"></div>
  <div class="parts back inner"></div>
</div>
```

## 配置

まず、コインを3D的に表現するにあたって `transform-style: preserve-3d;` を親要素に設定します。
今回はパーツの `div` 達を `.coin` で囲んでいます。

```css:css
.coin {
  transform-style: preserve-3d;
}
```

そして表面、裏面のパーツを `translateZ` でZ軸方向に移動させています。
表面は手前に、裏面は奥に移動させました。

```css:css
.front {
  transform: translateZ(5px);
}

.back {
  transform: translateZ(-5px);
}
```

これまで作ってきたコインのままでは、回転したときに内側の暗い色が見えてしまいます。
側面がないため、隠すことができません 😭
![回転したときに裏が見えてしまう図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821910/26347fb4-c2c5-8400-43f7-8a47e2d45b84.png)
そのため、暗い色の部分は `.inner` という別の `div` に分けています。
表面、裏面より `1px` 外側に配置しました。

```css:css
.front.inner {
  transform: translateZ(6px);
}

.back.inner {
  transform: translateZ(-6px);
}
```

最後に側面ですが、コインの側面を**まあるく沿わせる**といったことはCSSではできません。
ただの長方形を90度回転させた状態で中央に配置することで、
**横から見たときに表面と裏面の隙間が埋まる**ように見せています。

```css:css
.side {
  left: 50px;
  transform: rotateY(90deg);
}
```

このコインを上から見ると、下の図のようなイメージになります。**スカスカ**です。
![回転するコインを上から見た図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821910/e3ab0991-7ef4-7df1-e02d-b2e2daf1724a.png)
真横から見る分には、なんとなく隙がない感じになります。
![回転するコインを横から見た図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821910/1f85a57e-d604-cf0c-6cf5-75780eeb2a32.png)
※ 図はあくまでイメージです。実際の図形に厚みはありません。
※ CSSの限界と自分の技術不足により側面の柄は諦めました 😢

# まとめ

簡易的なデザインですが、CSSだけでコインを作ることができました。
仕事で使うかどうかはさておき、CSSの勉強にもなったのでよかったです。

いろいろカスタマイズもできそうなので、どなたかの参考になれば幸いです。