ホバーで枠線を出すときは border ではなく box-shadow で描く(周りがずれない)
:hover で border: 1px を足すと要素が 2px 大きくなって隣がガタつくので、box-shadow: 0 0 0 1px で同じ見た目の線を描き、レイアウトを動かさない。
どんな時に使う?
タグ(チップ)・カード・リスト項目など、横に並んだ要素にホバーやフォーカスで枠を付けたいとき。border は要素のサイズに含まれるため、付けた瞬間に幅と高さが増え、後ろの要素や行の折り返しが1px単位でずれて「ピクッ」と動いて見える。
コード
css
.chip {
border-radius: 999px;
transition: box-shadow 0.15s;
}
.chip:hover {
/* ぼかし 0・広がり 1px の影 = 1px の枠線 */
box-shadow: 0 0 0 1px rgb(0 0 0 / 0.3);
}box-shadowはボックスサイズにもレイアウトにも影響しないので、周りの要素は一切動かない。- 角丸にも沿って描かれ、
transitionで色や太さをなめらかに変えられる(borderの幅をアニメーションさせるとレイアウトが毎フレーム走る)。 - 線を内側に描きたいときは
inset 0 0 0 1px ...にする。
ほかのやり方
- 最初から
border: 1px solid transparentを付けておき、ホバーで色だけ変える。サイズが常に同じなのでずれない。 outlineもサイズに含まれない。内側に引き込むなら 白背景の商品画像に outline-offset: -1px で内側の縁取りを付ける と同じ考え方が使える。
注意点・対応状況
- すでに
box-shadowで影を付けている要素では上書きになるので、カンマ区切りで枠と影を並べて書く(box-shadow: 0 0 0 1px ..., 0 4px 12px ...)。 - ハイコントラストモード(
forced-colors: active)ではbox-shadowが描かれない。フォーカス表示など見えないと困る線はoutlineを使う。 overflow: hiddenの親の端にある要素だと、外側の影が切れることがある。その場合はinsetにする。
出典
- @nexvyn(2026-11-03)