ISIRMT Logo

「WELCOME」のテキストが見え隠れしたり跳ねたりするアニメーションを作った

こんにちは。CSS のお時間がやってきました。

アニメーション

アニメーションって組み合わせができるのですよね!(animation)複数の組み合わせで1つの動きのあるアニメーションの作成を目指します

完成物

デモ

実際にアニメーションのデモンストレーションページを用意しました。

https://isirmt.github.io/TemplateCSSAnimation/up_welcome/

↑よりぜひアクセスしてください。

ソースコード

https://github.com/isirmt/TemplateCSSAnimation/blob/main/up_welcome/index.html

にてアニメーションの全容を掲載しています。ご自由にお使いください。使う際にDelete HereとHeadのメタさえ消せば直ぐに利用可能です。

何を作るか

今回は,「O」の文字が遅れて現れ,ライン上に飛び乗ってフェードアウトするアニメーションを作ります.

まず,HTML側のエレメントとして次を用意しました.

<無題>html
<div class="welcome_container">
  <span>W</span>
  <span>E</span>
  <span>L</span>
  <span>C</span>
  <span>O</span>
  <span>M</span>
  <span>E</span>
</div>

.welcome_containerでトップのコンテナーを指定可能にし,子要素のspanは:nth-child(n)で指定可能な状態になっています.1

アニメーションは重ね掛けできる

章の題にある通り,アニメーション,すなわちkeyframesは複数作ったうえで,同じエレメントに重ねることができます.

実際に:nth-child(5)に限定した指定を見てみると

<無題>css
.welcome_container span:nth-child(5) {
  animation:
    up 0.7s ease-out 1s forwards,
    landing 0.6s cubic-bezier(.08, .47, .46, 2.84) 2s forwards,
    to_center 0.5s cubic-bezier(.58, -0.81, .16, 1.55) 3s forwards,
    out 0.3s ease-out 3.6s forwards;
}

4つだって重ねることができます.

重ねるうえでの注意点

気を付けないといけないこととして,主に2点.

  1. delayをdurationも加味した時間だけ遅らせる

つまり,ただ並べただけで順繰りに実行されるわけではないということです.transformプロパティの採用率は高いと思われますが,アニメーションの動作が競合すると期待している動作とは異なる形になるのでお気をつけて.

  1. fromや0%内のプロパティ指定

引き継ぐ前のアニメーションの状態を同じように指定してあげることで解決可能です.

メリット

勿論,1つのアニメーションに0%から○%と指定していき細かい制御を全て任せることも可能ですが,cubic-bezier()やeaseによるイージングプロパティの制御が移動や状態遷移ごとに設定しやすい点が大きいです.

デメリット

難しい点としては複雑な移動ができる分全体のループはしにくいと思います.

恐らくCSSだけでは無理かな...?(待ち時間も含めたアニメーションなら可能なのですが,区間ごとにイージングを設定する場合は厳しいと思ってます)

解決策としてはJSでアニメーションの終わりを検知(animationend)してクラス名の入れ直し,またはDOMの複製からの再配置が良いと思います.記述の入りはこのような感じです.

アニメーション終了のトリガーjs
element.addEventListener("animationend", () => {
  console.log("アニメーション終了");
});

https://developer.mozilla.org/ja/docs/Web/API/Element/animationend_event

ポイント

弾みの追加

「O」の文字が弾んだりするためにキーフレームで横や縦への伸ばしを設定しています.

<無題>css
@keyframes landing {
  0% {
    transform: translateY(1rem);
  }

  50% {
    transform: translateY(-0.2rem) scaleX(70%) scaleY(110%);
  }

  70% {
    transform: translateY(0.7rem) scaleX(110%) scaleY(60%);
  }

  100% {
    transform: translateY(0.2rem);
  }
}

マスク(overflow)

divで作った領域をoverflow: hiddenで見え隠れしたテキストを実現していました.

しかし,oの文字をフェードアウトする時に,div領域を飛び出て見せるためにはoverflow: visibleにする必要があります.同時に,隠れたテキストは見せないままである必要が...

今回はabsoluteにて設置しているわけではなく,テキストをspanで平置きしているだけです.

display: noneは消滅によるずれが発生するので使えません.そこで,レイアウトを崩さずに表示を消すのに役立つのがvisibility: hiddenです.

テキストがずれることなく隠せるので,マスク処理のオンオフで重宝します.

Footnotes

  1. oは5番目になるので沢山魔改造します ↩