【CSS】animationプロパティを使ったマウスホバーエフェクトの巻き戻し

CSSでマウスホバーエフェクトといえばtransition
プロパティを使ってアニメーションさせることが多いと思いますが、少し複雑なアニメーションをさせたい時はtransition
では難しいことがあると思います。
そんな時は、hover疑似クラスと合わせてanimation
プロパティを使い、@keyframes
でうまいことやるといい感じにすることができるので、個人的にはよく使っているのですが、animation
プロパティでは、マウスアウト時にアニメーションが行われず、瞬時に元の位置へ戻ってしまい、少し不格好になってしまうのが悩みの種でした。
これを何とかしたくて色々やってみた結果、すごくシンプルな方法ですが、animation
プロパティでもマウスアウト時にアニメーションさせることができたので、簡単にご紹介します。
マウスアウト時の挙動
とりあえず、それぞれのマウスアウト時の挙動を確認します。
transitionプロパティの場合
transition
プロパティでホバーアニメーションをさせた場合、対象の要素からマウスアウトすると、アニメーションしながら元の位置へ戻ります。
マウスホバー、マウスアウト両方でアニメーションする
CSSは以下の通り(抜粋です)。
.hover-transition {
position: relative;
}
.hover-transition::before {
content: "hover →";
position: absolute;
transition: all .5s ease-out;
}
.hover-transition:hover::before {
content: "← mouse out";
transform: translateX(200px);
}
animationプロパティの場合
animation
プロパティを使用した場合は、対象の要素からマウスアウトした後はアニメーションは行われず、瞬時に元の位置へ戻ってしまいます。なお、animation
でのホバーエフェクトは、hover擬似クラスにanimation
プロパティを指定します。
マウスアウト時にはアニメーションしない
CSSは以下の通り(抜粋です)。
.hover-animation {
position: relative;
}
.hover-animation::before {
content: "hover →";
position: absolute;
}
.hover-animation:hover::before {
content: "no animation";
animation: anim .5s ease-out forwards;
}
@keyframes anim {
0% {transform: translateX(0);}
100% {transform: translateX(200px);}
}
animation
プロパティの場合、animation-fill-mode
でアニメーション実行後のスタイルを指定することができますが、これはあくまでもアニメーションが終了した直後のスタイルを指示するだけで、マウスアウト時のスタイルを指定することはできません。
上記では、forwards
を指定し、最後に適用したキーフレームの値を維持させるようにしています。
上記のような簡単なマウスホバーエフェクトであれば、transition
でも十分ですが、複雑なアニメーションをさせるような場合には、やはりanimation
プロパティが必要で、その場合、マウスアウト時のアニメーションは諦めるしかありませんでした。
animationプロパティでもマウスアウト時にアニメーションさせる
前置きが長くなってしまいましたが、ここからが本題です。
animationプロパティでマウスアウト時にアニメーションさせるには、逆再生(巻き戻し)用のkeyframesを別で用意して、元の要素にもanimationプロパティを指定することで実現できます。
両方でanimationプロパティを指定した場合
実際にanimation
プロパティを使って、マウスアウト時にもアニメーションを付与させたものが以下です。
マウスホバー、マウスアウト両方でアニメーションする
CSSは以下のような感じになります(抜粋です)。
.hover-animation2 {
position: relative;
}
.hover-animation2::before {
content: "hover →";
position: absolute;
animation: anim-out .5s ease-out forwards;
}
.hover-animation2:hover::before {
content: "← mouse out";
animation: anim .5s ease-out forwards;
}
@keyframes anim {
0% {transform: translateX(0);}
100% {transform: translateX(200px);}
}
@keyframes anim-out {
0% {transform: translateX(200px);}
100% {transform: translateX(0);}
}
hover-animation2 というクラスの通常時とホバー時に、それぞれ別々のkeyframes
を指定しています。
応用
上記の方法を使うと、以下のようなtransition
ではできない、少し複雑なホバーエフェクトができるようになります。
こんなのとかも。
気になる点
上記の方法で、一応は解決はしたんですが、これを使った場合に2点ほど気になる点が出てきました。
1つは、通常時の要素にanimation
プロパティを指定しているため、ページロード時に必ず一度だけそのアニメーションが実行されてしまうという点と、もう一つはアニメーションの途中でマウスアウトすると挙動がおかしくなるという2点です。
前者は、対象の要素が見える位置でリロードしてみるとよく分かるんですが、ページが表示されるタイミングで、巻き戻し用のアニメーションが実行されてしまいます。これを防ぐことは(多分)できないんですが、durationの長さに合わせて、ページロードから2秒間だけとかローディング画像的なものを表示させるようにすれば、不自然には見えないんじゃないかなと思っています。
ただ、前者の場合は、アバブ・ザ・フォールドに対象の要素がなければ、見えないところで勝手にアニメーションが実行されるだけなので、そこまで気にならないかもしれません。移動系のアニメーションの時は注意する必要があるかもしれませんが(ネタバレ注意的な意味で)。
後者についてはもうどうしようもできないので、せめて途中でマウスアウトされないように、印象的かつ効果的なアニメーションの作成を心がけるしかないかなと思います。。
おわり
気になる点については、JavaScriptを使えば何とかなるかもしれませんし、そもそもアニメーションはJSでやればいいと言われればそれまでなんですけど、個人的に、マウスのホバーエフェクトでJSは使いたくない派なので、この方法は結構気に入っています。
CodePenに上記全てのDEMOを掲載していますので、コードについての詳細はそちらをご覧ください。