シンプルなフェードインでCSSアニメーションの基礎を学び直す

## 概要

書いているうちにゴチャゴチャして混乱しがちな animation プロパティの記述をスッキリさせたいので、シンプルなフェードインでCSSアニメーションの基礎を学び直してみました。

## 基本のサンプル

3つの円が重なっているものを用意しました。

<img width="200" alt="スクリーンショット 2020-01-25 5.43.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/3e6e62cb-d9ae-5873-2a66-0400451ba0e3.png">

### HTML

```HTML
<div class="wrapper">
  <div class="item is-1"></div>
  <div class="item is-2"></div>
  <div class="item is-3"></div>
</div>
```

`.wrapper` で囲んでいるのは見た目の調整だけなので深い意味はありません。
以降、HTML に変更はないのでサンプルへの記述は省略します。

### CSS

```css
.wrapper {
  margin: 20px;
  position: relative;
}

.item {
  position: absolute;
  width: 300px;
  height: 300px;
  border-radius: 50%;
  opacity: 0.5;
}
.is-1 {
  top: 0;
  left: 0;
  background: blue;
}
.is-2 {
  top: 50px;
  left: 50px;
  background: yellow;
}
.is-3 {
  top: 100px;
  left: 100px;
  background: red;
}
```

`.item` クラスに基本のスタイルを指定し、
`.is-1` `.is-2` `.is-3` に位置と色をそれぞれ指定してあります。
この状態だとまだアニメーションしません。

## 最低限必要なアニメーションのプロパティ

フェードインをさせる前に、CSS アニメーションのプロパティを最低限なものだけ挙げてみます。

### `animation-duration` プロパティ

[animation-duration - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/animation-duration)
アニメーションが完了する周期。
値を小さくすればすばやくなり、大きくすればのんびりになる。

今回は1秒（1s）で。

```
animation-duration: 1s;
```

### `animation-name` プロパティ

[animation-name - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/animation-name)
要素に適用されるアニメーションの名前を指定する。
アニメーションの名前は、`@keyframes` で用意する（後述）
複数の指定も可能。

今回はふわっと表示させるフェードインを作るので、

```
animation-name: fadeIn;
```

としました。

### `animation` プロパティ

[animation - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/animation)
アニメーションのショートハンド。アニメーション系の値をまとめて書ける。
値をを半角スペースで区切って書く。

上記に書いたプロパティをまとめると、

```
animation: 1s fadeIn;
```

と書けます。

### `@keyframes` @-規則

[@keyframes - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/@keyframes)
アニメーションの流れに沿いつつアニメーション中の中間のステップも制御しながらスタイルを定義する。
CSS トランジションよりも詳細に制御や調整ができる。
キーフレームは `from` `to` か、`0%` 〜 `100%` で指定する。

パーセンテージのほうが細かく調整できますが、今回は難しいことはしないので、

```css
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 0.5; }
}
```

`from` `to` を使って、上記のようにしました。
名前は、さきほど `animation-name` で指定した `fadeIn` にしてあります。

## フェードインができそうでできなかった例

フェードインのシンプルな例は、`animation` プロパティと `@keyframes` @-規則 で、

```css
(アニメーションさせたいセレクタ) {
  animation: 1s fadeIn;
}

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 0.5; }
}
```

このような書き方で行けそうですが、落とし穴がありました…

### ダメだったサンプル

上のコードをサンプルに適用します。

**CSS**

- `opacity` の初期値をゼロに
- アニメーションの記述を追加

```css
.wrapper {
  margin: 20px;
  position: relative;
}

.item {
  position: absolute;
  width: 300px;
  height: 300px;
  border-radius: 50%;
  opacity: 0; /* ←初期値を変更。透明に。*/
  animation: 1s fadeIn; /* ←追加 */
}

.is-1 {
  top: 0;
  left: 0;
  background: blue;
}
.is-2 {
  top: 50px;
  left: 50px;
  background: yellow;
}
.is-3 {
  top: 100px;
  left: 100px;
  background: red;
}

@keyframes fadeIn { /* ←追加 */
  from { opacity: 0; }
  to { opacity: 0.5; }
}
```

やってみると、

![サンプル画像：フェードインするものの消えてしまう3つの円](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/ea9ad10e-f81b-e359-c012-7d86dc98421e.gif)

**消える……。** 
※GIFはループしていますが実際は1回きりです。
[CodePen のサンプルはこちら](https://codepen.io/becolomochi/pen/xxbBdyg)
終了時のスタイル指定をしていないため、初期値の `opacity: 0` が効いてしまうためです。

## フェードインをフェードインらしく改善

プロパティ `animation-fill-mode` を使います。

### `animation-fill-mode` プロパティ

[animation-fill-mode - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/animation-fill-mode)
CSS アニメーションの開始と終了時にどういったスタイルを適用するかを指定できる。

今回は、表示されたままにしたい＝最後で止めたいので、`forwards` を指定します。
ショートハンドで書かない場合は、

```
animation-fill-mode: forwards;
```

animation ショートハンドなら、以下のように値を追加します。

```
(アニメーションさせたいセレクタ) {
  animation: 1s fadeIn forwards;
}
```

### 正しいサンプル

以下のサンプルで3つの円をフェードインすることができました。

[CodePen のサンプルはこちら](https://codepen.io/becolomochi/pen/bGNZWxz)

**CSS**

```css
.wrapper {
  margin: 20px;
  position: relative;
}

.item {
  position: absolute;
  width: 300px;
  height: 300px;
  border-radius: 50%;
  opacity: 0; /* ←初期値を変更。透明に。*/
  animation: 1s fadeIn forwards; /* ←追加 */
}

.is-1 {
  top: 0;
  left: 0;
  background: blue;
}
.is-2 {
  top: 50px;
  left: 50px;
  background: yellow;
}
.is-3 {
  top: 100px;
  left: 100px;
  background: red;
}

@keyframes fadeIn { /* ←追加 */
  from { opacity: 0; }
  to { opacity: 0.5; }
}
```

誰もが想像できるフェードインになりました。

![サンプル画像：フェードインらしく表示され続ける円](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/a6e327e0-e3eb-0c0f-9203-5e8d9d1c8cb5.gif)


## フェードインでばらばらと表示させたい

3つもアイテムがあるのでばらばらと表示させてみます。
必要なプロパティは、`animation-delay` です。

### `animation-delay` プロパティ

[animation-delay - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/animation-delay)
アニメーションをいつ開始するかを秒数で指定できる。

```
animation-delay: 3s;
```

ショートハンドなら、

```
(アニメーションさせたいセレクタ) {
  animation: 1s fadeIn 3s forwards;
}
```

と書けます。
今回のサンプルではショートハンドは使わず、ひとつひとつに数値を与えます。

### サンプル

[CodePen のサンプルはこちら](https://codepen.io/becolomochi/pen/XWJGRPd)

**CSS**

- 1つ目の青い円が1秒遅れ
- 2つ目の黄色い円が2秒遅れ
- 3つ目の赤い円が3秒遅れ

にしてみます。

```css
.wrapper {
  margin: 20px;
  position: relative;
}

.item {
  position: absolute;
  width: 300px;
  height: 300px;
  border-radius: 50%;
  opacity: 0; /* ←初期値を変更。透明に。*/
  animation: 1s fadeIn forwards; /* ←追加 */
}

.is-1 {
  top: 0;
  left: 0;
  background: blue;
  animation-delay: 1s; /* ←さらに追加 */
}
.is-2 {
  top: 50px;
  left: 50px;
  background: yellow;
  animation-delay: 2s; /* ←さらに追加 */
}
.is-3 {
  top: 100px;
  left: 100px;
  background: red;
  animation-delay: 3s; /* ←さらに追加 */
}

@keyframes fadeIn { /* ←追加 */
  from { opacity: 0; }
  to { opacity: 0.5; }
}
```

ひとつずつ順番に表示されるようになりました。

![サンプル画像：ばらばら表示される円のGIFアニメーション](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/977312fa-6e87-ab84-79a8-06261c660243.gif)

## 今後

他にもアニメーションを制御するプロパティがあるのでこちらも調べてみます。

## 参考

[animation - CSS: カスケーディングスタイルシート | MDN](https://developer.mozilla.org/ja/docs/Web/CSS/animation)