transform: scale()で画像がカクつく・ずれるときの対処法|rotate(0.001deg)で改善したケース

transform: scale()で画像がカクつく・ずれるときの対処法と、ホバーするカード画像を図案化したアイキャッチ CSS
※この記事には広告を含みます / This article contains advertising.
スポンサーリンク

カードをホバーしたとき、画像がふわっと少し拡大する演出はよく使いますよね。

ところが、transform: scale()で拡大しているだけなのに、ホバーを外した直後に画像がわずかにずれたり、動きが滑らかに見えなかったりすることがあります。

この記事では、Windows版Chromeで、カード画像をscale(1.05)から元に戻したあとに左へわずかにずれる症状が出たケースをもとに、解決方法のひとつをご紹介します。

先に結論をお伝えすると、rotate(0.001deg)を加えて直ることがあります。ただし、これはどの環境でも保証される万能な解決策ではありませんので、ご了承くださいませ…

本記事の執筆者:マサトラ

フリーランス歴4年のWebエンジニア。現在は20社以上のWeb制作会社社様と提携し、WordPress構築やLP制作を中心に月3~5件のペースでサイト制作を手がけています。
このブログでは、実務で得た知識やノウハウ、制作現場での気づきを、フリーランスとして活動中の方はもちろん、これからWeb制作を仕事にしたいと考えている方にも役立つよう発信しています。

スポンサーリンク

今回起きた症状と実案件の構造

今回のカードは、上部が画像、下部がテキストという構成です。よく見かけるヤツですね。カードをホバーすると、画像だけを1.05倍に拡大するようにしていました。

.card__media {
  height: 376px;
  overflow: hidden;
}

.card__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.25s ease;
}

.card:hover .card__image {
  transform: scale(1.05);
}

実装後、Windows版Chromeで確認したところ、ホバーを外して画像サイズが元に戻ったあと、画像が左へわずかにずれることがありました。

ちなみに、今回の症状では、transform-origin: center centerで拡大の基準位置を指定しても改善しませんでした。transform-originは「どこを基準に拡大するか」を決めるプロパティで、ホバー解除後にだけ起きる位置ずれを直すものではないということかもしれません。

rotate(0.001deg)で改善した書き方

結局、このケースでは、scale()と一緒に、ごく小さい角度のrotate()を指定すると症状が解消しました。

.card__image {
  display: block;
  width: 100%;
  transform: scale(1) rotate(0.001deg);
  transition: transform 0.25s ease;
}

.card:hover .card__image {
  transform: scale(1.05) rotate(0.001deg);
}

ポイントは、通常時とホバー時の両方に同じrotate(0.001deg)を入れることです。transformは値をまとめて上書きするため、片方だけに書くと、意図しない切り替わりになりやすいためです。

この方法は、微小な回転によってブラウザの描画経路が変わり、結果として見た目が安定することがある回避策で、実際にIE11で同様のscale()のカクつきをrotate(0.001deg)で回避した事例もあるようです。

ただし、CSSの仕様として「微小な回転を入れれば滑らかになる」と保証されているわけではないのでご注意を。たまたま今回のWindows版Chromeでは改善しましたが、別のChromeバージョン、Safari、Firefox、端末では同じ結果になるとは限らないので…

スポンサーリンク

追加する前に確認したいこと

rotate(0.001deg)を足す前に、次の順番で見ていくと原因を絞り込みやすくなります。

1. 画像以外も同時に動かしていないか

カード全体にtransition: allを指定していると、色・影・幅・位置など、意図しないプロパティまでアニメーションすることがあります。

画像を拡大するだけなら、transition: transformのように対象を限定しましょう。box-shadowfilterclip-pathなどの重い処理を同時に動かしている場合も、いったん外して差を確認します。

2. 親要素と画像の役割を分けられているか

カード全体を拡大すると、テキスト、影、リンクのクリック領域まで一緒に変形します。画像だけを見せたい演出なら、切り抜き用の親要素と、拡大するimgを分けるほうが原因を追いやすくなります。

また、imgにはdisplay: blockを指定して、インライン要素由来の余白が混ざらないようにしておくと安心です。

3. transform-originが必要な症状かを見分ける

今回のように、transform-origin: center centerを指定しても「ホバー解除後にだけ位置がずれる」場合は、基準位置の問題ではない可能性があります。

一方、拡大中から画像が常に同じ方向へ大きくなって見える場合は、基準位置の問題かもしれません。その症状に限って、次のようにtransform-originを指定します。

.card__image {
  transform-origin: center center;
}

今回のように「サイズが戻ったあとだけ位置がずれる」場合は、transform-originを何度も調整するのではなく、rotate(0.001deg)を含む回避策を試す候補になると思います。

rotate(0.001deg)を使うときの注意点

今回のように対象環境で改善を確認できたなら、限定的に使う選択肢はあります。その際は、次を確認してみてください。

  • 画像がぼやけたり、文字がにじんだりしないか
  • z-indexや重なり順が変わっていないか
  • position: fixedの子要素など、変形の影響を受ける要素を含んでいないか
  • PCだけでなく、実際に対象とするスマートフォンでも見た目に問題がないか
  • 通常時とホバー時で、同じtransform関数を指定しているか

transformを指定した要素は、重なり順に関わることがあります。今回のように画像だけへ適用するなら影響は少ないですが、カード全体や大きな親要素へ付ける場合は注意が必要です。

まとめ

transform: scale()のアニメーションで画像がカクつく、またはホバー解除後にずれるときは、まず画像を切り抜く親要素と、拡大する画像の役割が分かれているかを確認してみてください。拡大中から方向が偏る場合だけ、transform-originを確認します。

今回のWindows版Chromeのカード画像では、rotate(0.001deg)を加えることで、ホバー解除後に左へずれる症状を解消できました。ただし、これはたまたま有効だった回避策です。

rotate(0.001deg)を追加したら、通常時とホバー時の両方に書き、対象ブラウザで画像のぼやけや位置ずれがないかを確認するようにしましょう!

参考資料

スポンサーリンク