トランジションアニメーションを@keyframesで作る方法

## どういうことか
CSSで複雑な遷移アニメーションを作りたいと思ったことはありませんか？私はよくあります。
ですが、`transition`による指定では`from`と`to`の2状態間の遷移しか定義できません。例えば、次のアニメーションキーフレームを`transition`で定義することはできないのです。

```css
@keyframes {
  0% {
    opacity: 0;
  }
  75% {
    opacity: 1;
  }
}
```
そこで、CSSアニメーションの仕様を使ってJavaScriptを使わずに上のような遷移アニメーションを実装してみようと思います。

結論から言うと、`animation-fill-mode`というCSSプロパティを指定すれば実現できます。このプロパティは、アニメーションの再生の前後の要素の状態(スタイル)を指定するものです。
下にそれぞれの値でどのようにアニメーションが変化するのか置いておきます。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="css,result" data-user="boufrawfrodo2" data-slug-hash="gObaXmX" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="animation-fill-modeのデモ">
  <span>See the Pen <a href="https://codepen.io/boufrawfrodo2/pen/gObaXmX">
  animation-fill-modeのデモ</a> by Frodo la Intermeza Programisto (<a href="https://codepen.io/boufrawfrodo2">@boufrawfrodo2</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

`backwards`と`both`だけちょっとわかりにくいですが、`backwards`は最初`animation-delay`プロパティでアニメーションの実行が遅延されている間`from`または`0%`(`animation-direction`が`nomal`か`alternate`の場合、`reverse`か`alternate-reverse`なら`to`か`100%`)のスタイルを維持します。`both`は文字通り`forwards + backwards`ですね。

## 実際にやってみる
さて、この`animation-fill-mode`ですが、デフォルト値が`none`のため、アニメーション再生終了後`keyframe`のスタイルは破棄されます。そこでこれの値を`forwards`しておけば、アニメーション終了後、つまり遷移完了後も`keyframe`のスタイルが維持され続けるというわけ。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="css,result" data-user="boufrawfrodo2" data-slug-hash="povjdOX" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="@keyframesを使った遷移アニメ">
  <span>See the Pen <a href="https://codepen.io/boufrawfrodo2/pen/povjdOX">
  @keyframesを使った遷移アニメ</a> by Frodo la Intermeza Programisto (<a href="https://codepen.io/boufrawfrodo2">@boufrawfrodo2</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

すみません、アドベントカレンダー記事なのに非常に内容が薄い記事でした。

## もう少しだけ続くんじゃ
そもそもなんでこんなこと調べたかというと、javascriptを使ったアニメーションが好きではないからでした。ぶっちゃけてしまえば、このテクニックでjavascriptアニメーションの9割は消えると思っています。CSSでは実現できない残りの1割って何でしょう？

どれだけ考えてもCSSだけで実現する方法が思いつかなかったアニメーションとは、最近のUIデザインでもよくつかわれる、クリックした座標に効果をつけるアニメーションです。こちらの場合、アニメーションの部分はCSSで実装できます。が、クリックした座標に要素を作成したり動かしたりするのは今のところCSSでは無理です。`attr()`CSS関数が`content`以外の要素でもサポートされるようになれば希望はありますが、今は無理。CSSだけでアニメーションを完結させるのはまだ難しそうです。

ぶっちゃけパスデータ弄って形変えたりするのは、ほとんど`shape-outside`プロパティで代用できます。面倒くさいけど。ただまぁ、CSS Shapes Module Level 1は2019年12月現在でCandidate Recommendationなので、まだ使っていいか微妙なところですが……。とはいえ、IEとEdge以外の主要ブラウザはかなり前からサポートしてますし、普通にプロダクトに使うのに十分そうではあります。いうものの、サポートしているブラウザも完全にサポートしているわけではなく、例えば`path()`CSS関数はほとんどすべてのブラウザでサポートされていません。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="css,result" data-user="boufrawfrodo2" data-slug-hash="BayoJaM" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="shape-outsideでそれっぽくアニメーション">
  <span>See the Pen <a href="https://codepen.io/boufrawfrodo2/pen/BayoJaM">
  shape-outsideでそれっぽくアニメーション</a> by Frodo la Intermeza Programisto (<a href="https://codepen.io/boufrawfrodo2">@boufrawfrodo2</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

現状ではこれが限界ですし、こんなことするくらいなら圧倒的にjavascript使ったほうが簡単です……。

* [Can I use... CSS Shapes Level 1](https://caniuse.com/#feat=css-shapes)
* [Can I use... types: &lt;basic-shape&gt;: path()](https://caniuse.com/#feat=mdn-css_types_basic-shape_path)