ホバーで持ち上げるのはカード本体ではなく中の子要素にする(下端のチラつき防止)
.card:hover でカード自身を translate で上げると、下端付近でホバーが外れたり付いたりを繰り返すので、動かすのは内側の .inner にする。
どんな時に使う?
- カード、ボタン、リスト項目などに「ホバーで少し浮く」演出を付けるとき。
- ポインターをカードの下端に置くとガタガタ震える、というバグ報告が来たとき。
なぜチラつくのか
カード本体を 6px 上に動かすと、ホバー判定の領域(カードの箱)も一緒に 6px 上がる。ポインターが元の下端から 6px 以内にあると、領域の外に出てホバーが外れる → カードが元の位置に戻る → またポインターの下に来てホバーが付く…というループになり、下端 6px の帯で震え続ける。
ホバーを受ける要素(外側)は動かさず、見た目だけの子要素を動かせば、判定領域が変わらないのでループが起きない。
コード
html
<a class="card" href="…">
<div class="inner">…中身…</div>
</a>css
.card > .inner {
transition: translate 200ms ease;
}
.card:hover > .inner,
.card:focus-visible > .inner {
translate: 0 -6px;
}影や背景も .inner 側に付けておくと、浮いた見た目が自然になる。外側の .card は透明な「当たり判定」の箱として残る。
注意点
translateはレイアウトを変えないが、ホバーの判定は動いた後の位置で行われる。だから判定を受ける外側の要素は動かさないのがポイント。- キーボード操作でも同じ演出を出すなら
:focus-visibleも併記する。 prefers-reduced-motion: reduceのときは移動をやめて影の変化だけにするなどの配慮を。translateプロパティは全モダンブラウザ対応。