GODRICH
#cssアニメーション#ボタン#ローディング#トランジション#スクロール#ダッシュボード#実用ui#デザイントレンド

カード フリップ アニメーション 9選【コピペ20行】

カード フリップ アニメーションとは、マウスを乗せたりクリックしたりするとカードがくるっと回転したり半分に折れたりして、裏側の内容が現れる効果のことです。コードが分からなくても、下のデモにマウスを乗せてみれば何が起きているか一目で分かります。

自動再生 · タイルを押すとその項目へ · すべて1つのzip

9個は人気順ではなく、仕組みが単純なものから複雑なものへ、最後はアクセシビリティにつながる順番で並んでいます。もっとも基本のホバー反転(01)とクリック反転(02)から始めて、紙のように折って開くアイデア型の変形(03〜04)を経たあと、複数枚のカードを扱う実戦パターン(05〜08)に進み、同じカード反転をモーションを抑えて再生する09番で締めくくります。

01横に反転

css カード ホバー で回る

カードにマウスを乗せるとY軸を中心に180度回転し、裏面が現れます。

横に反転
新しいタブで開く

01 · 横に反転 — 計測 累積面積 13.071% · 動いたフレーム 7/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

rotateYperspectivebackface-visibility

どんなカードに使うか

クリックしなくても、見るだけで裏面が気になるカードに使います。

.fy-card { perspective: 700px; }
.fy-card__inner {
  transform-style: preserve-3d;
  transition: transform $duration $easing;
}
.fy-card:hover .fy-card__inner { transform: rotateY(180deg); }
.fy-card__face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
}
.fy-card__face--back { transform: rotateY(180deg); }

02縦に反転(クリック)

クリックで縦に反転

カードをクリックするとX軸を中心に縦に反転し裏面が表示されます。

縦に反転(クリック)
新しいタブで開く

02 · 縦に反転(クリック) — 計測 累積面積 12.343% · 動いたフレーム 8/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

rotateXaria-pressedJS 6줄

タッチ端末で確実な理由

タッチ端末はホバーがないため、クリック・タップで発動させます。

var btn = document.querySelector(".fx-card");
btn.addEventListener("click", function () {
  var open = btn.getAttribute("aria-pressed") === "true";
  btn.setAttribute("aria-pressed", String(!open));
  btn.classList.toggle("is-flipped", !open);
});

03半分に折る

中央の線で折りたたむ

カードが中央の線を基準に半分に折りたたまれ、内容が内側に隠れます。

半分に折る
新しいタブで開く

03 · 半分に折る — 計測 累積面積 13.074% · 動いたフレーム 19/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

preserve-3drotateYtransform-origin

紙のカードを閉じるように

紙のカードを閉じるように、メニュー表や案内カードを畳むときに使います。

.fh-half--fold {
  transform-style: preserve-3d;
  transform-origin: left center;
  transition: transform $duration $easing;
}
.fh-half__face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
}
.fh-half__face--back {
  background: rgba(23, 20, 26, .78);
  transform: rotateY(180deg);
}

04手紙を開く

上下2段が順番に開く

折りたたまれていたカードが手紙を開くように上下2段が順番に広がり、中身が現れます。

手紙を開く
新しいタブで開く

04 · 手紙を開く — 計測 累積面積 26.174% · 動いたフレーム 11/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

rotateXtransition-delaytransform-origin: top

封筒を開ける感覚

下の段だけ少し遅れて開くので、封筒を開ける感覚になります。

.ul-flap--top { transform-origin: top center; }
.ul-flap--bottom { transform-origin: bottom center; }

@keyframes ul-open-top {
  0%, 25%   { transform: rotateX(0); }
  60%, 100% { transform: rotateX(-172deg); }
}
@keyframes ul-open-bottom {
  0%, 40%   { transform: rotateX(0); }
  75%, 100% { transform: rotateX(172deg); }
}
.ul-scene .ul-flap--top { animation: ul-open-top ($duration * 2.6) $easing infinite; }
.ul-scene .ul-flap--bottom {
  animation: ul-open-bottom ($duration * 2.6) $easing infinite;
  animation-delay: 120ms;
}

05山札をシャッフル

一番上だけが動く

積み重なったカードの一番上が反転して後ろへ移動し、次のカードが見えるようになります。

山札をシャッフル
新しいタブで開く

05 · 山札をシャッフル — 計測 累積面積 10.424% · 動いたフレーム 10/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

z-indexrotateYtranslateZ

1枚ずつめくって見せる

レビューやおすすめ商品のカードを1枚ずつめくって見せたいときに使います。

.ss-card--2 { transform: translateZ(-16px) translateY($sp-2); opacity: .85; }
.ss-card--3 { transform: translateZ(-32px) translateY($sp-4); opacity: .65; }

@keyframes ss-shuffle {
  0%, 30%   { transform: translateZ(0) translateX(0) rotateY(0); opacity: 1; }
  70%       { transform: translateZ(-8px) translateX(-46px) rotateY(-150deg); opacity: .25; }
  71%, 100% { transform: translateZ(0) translateX(0) rotateY(0); opacity: 1; }
}
.ss-stack .ss-card--1 { z-index: 3; animation: ss-shuffle ($duration * 6) $easing infinite; }

06ページめくり

カード めくる アニメーション の基本

カードの右端を基準に本のページをめくるように回転し、下のカードが現れます。

ページめくり
新しいタブで開く

06 · ページめくり — 計測 累積面積 16.329% · 動いたフレーム 9/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

rotateYtransform-origin: rightbox-shadow

影も一緒に動く

影も一緒に動くので、紙がふわっと持ち上がる感覚が出ます。

.bp-page {
  transform-style: preserve-3d;
  transform-origin: right center;
  transition: transform $duration $easing, box-shadow $duration $easing;
}
.bp-page__face { backface-visibility: hidden; }
.bp-page__face--back { transform: rotateY(180deg); }

@keyframes bp-turn {
  0%, 30%   { transform: rotateY(0); }
  70%, 100% { transform: rotateY(-155deg); }
}

07価格を見せるカード

裏面に割引価格

カードにマウスを乗せると反転し、裏面に割引価格が現れます。

価格を見せるカード
新しいタブで開く

07 · 価格を見せるカード — 計測 累積面積 12.062% · 動いたフレーム 7/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

rotateYbackface-visibility: hidden180ms

1枚で見比べる

定価と割引価格を1枚のカードで見比べたいときに使います。

.rp-card__inner {
  transform-style: preserve-3d;
  transition: transform $duration $easing;
}
.rp-card:hover .rp-card__inner { transform: rotateY(180deg); }
.rp-card__face {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
}
.rp-card__face--back { transform: rotateY(180deg); }

084面キューブ

4つの面を持つカード

カード1枚が立方体のように4つの面を持ち、クリックするたびに1面ずつ回転します。

4面キューブ
新しいタブで開く

08 · 4面キューブ — 計測 累積面積 12.789% · 動いたフレーム 12/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

preserve-3dtranslateZrotateY

1枚にまとめたいとき

画像・説明・価格・購入ボタンを1枚のカードにまとめたいときに使います。

var cube = document.querySelector(".cb-cube");
var step = 0;
cube.addEventListener("click", function () {
  step = (step + 1) % 4;
  cube.style.setProperty("--cb-step", String(step));
});

09モーション削減版

回転の代わりにクロスフェード

同じカード反転をprefers-reduced-motionが有効な環境で再生すると、回転の代わりに柔らかいクロスフェードに切り替わります。

モーション削減版
新しいタブで開く

09 · モーション削減版 — 計測 累積面積 10.497% · 動いたフレーム 20/23GODRICH オリジナル · SCSS と React は zip に同梱 · パスワードを見る

prefers-reduced-motionopacitytransition

切り替え自体を見せる

この項目はその切り替え自体を見せています。

@media (prefers-reduced-motion: reduce) {
  .rm-card:hover .rm-card__inner { transform: none; transition: none; }
  .rm-card:hover .rm-card__face--front {
    opacity: 0;
    transition: opacity $dur-base $ease-out;
  }
  .rm-card:hover .rm-card__face--back {
    opacity: 1;
    transform: none;
    transition: opacity $dur-base $ease-out;
  }
}

カード フリップはどこで壊れるか

90度直前ににじむ文字

もっとも先に見つかった落とし穴は03番の半分に折るカードでした。折れる側の面にはbackface-visibility: hiddenを掛けてあるので裏面がこちら向きになった瞬間はきちんと消えますが、回転角度がちょうど90度に近づく直前のフレームでは面がまだ完全に垂直を超えておらず、遠近法で押しつぶされた極細の文字がうっすらと透けて見えます。hiddenは面が90度を超えてはじめて完全に消える仕組みで、それまでは元の角度のまま描画され続けるためです(MDNのbackface-visibilityドキュメントを参照)。実際に撮影したフレーム画像(回転角90度付近の1枚)でも、この薄いにじみをはっきり確認できました。

translateZ がずれると

08番の4面キューブにも似た落とし穴があり、4つの面をつなぎ合わせるときに使うtranslateZの値がカード1辺の半分と正確に一致していないと、面と面の間にすき間ができたり、逆に重なって見えたりします。110pxのカードならtranslateZは必ず55pxにしないと、面がずれて立方体に見えなくなります。どちらも一コマずつ確認してはじめて気づけた不具合で、通しで再生しただけでは見逃していました。9個のファイルが入ったzipの合言葉はzmahx9ysで、解凍するとvanillaフォルダとreactフォルダがそれぞれ入っています。

アクセシビリティ — 9個がreduced-motionで残すもの

項目ごとに反応が違う

システムで動作を減らす設定を入れている場合、項目ごとに反応が違います。01・02・07番はtransform: none !importantで反転自体が止まるため、マウスを乗せてもクリックしても裏面は一切見えず表面のままです — 裏面の情報が必要なら、別のボタンなど反転以外の手段を用意する必要があります。

08番は切り替えだけ止まる

08番はクリックで状態が変わること自体はそのままに、なめらかな切り替えだけを止めるので、クリックすると一瞬でぱっと切り替わります。03・04・05・06番はそもそもホバーやクリックのトリガーがなく自動再生ループだけなので、動作を減らす設定と一緒に消える対象自体がありません。

09番の解き方

09番はこの切り替え自体がテーマなので、回転の代わりにopacityのクロスフェードだけを残す様子を常に見せるように作ってあります。カード反転以外のフィードバック系アニメーションが気になる方は価格表アニメーション9選も参考になりますし、クリックで反応するUIはクリック・タッチのフィードバックアニメーション9選でも探せます。ほかのCSSアニメーションはCSSカテゴリーからまとめて見られます。

FAQ

css カード アニメーション はどのブラウザでも同じように見えますか?

rotateY・rotateXとpreserve-3dは最新のChrome・Edge・Safari・Firefoxのすべてで動作します。ただしごく古いブラウザでは3D回転なしにカードの内容がそのまま切り替わって見えることがあるため、決済のような重要な画面では、クリックでも同じ情報を確認できる代替手段を一緒に用意しておくと安全です。

JSなしでカードを反転できますか?

はい、01・07番のように:hoverで発動するカードはCSSだけで十分です。反転した状態を覚えておく必要がある02・08番はクリックのたびに状態を保存しなければならないため、JavaScriptが6〜8行だけ必要になります。

zip内のvanillaとreactのコードは違いますか?

画面で見える動き自体は同じです。vanilla側はSCSSファイルの先頭でduration・easing・colorの3つの変数を直接書き換え、react側は同じ値をコンポーネントのpropsとして受け取り、--durationのようなCSSカスタムプロパティに渡している点だけが異なります。

解凍パスワードを入力してください

パスワードはこの記事の本文の中にあります。読み進めると出てきます。