PC では自然に見える :hover の演出も、iPhone では思わぬ挙動になることがあります。
よくあるのが、タブ切り替えボタンをタップしたあとも :hover の見た目が残る というケースです。
これは CSS の書き方ミスというより、タッチ端末と :hover の相性 によるものです。ここでは、なぜ起きるのかと、どう書き分けると安定しやすいかを整理します。
:hover は本来マウス向け
:hover は、本来「ポインタが要素の上に乗っている状態」です。
a:hover {
opacity: 0.7;
}
PC では「マウスを乗せたら反応し、離したら戻る」なので直感的です。
ただし iPhone のようなタッチ端末には、常時乗っているポインタがありません。
そのため Safari は、場面によって タップを hover の代わりのように扱う ことがあります。結果として、タップ後に :hover 相当の見た目が残ることがあります。
なぜタブボタンで起きやすいのか
タブ切り替え UI では、見た目の変化が複数あります。
- PC でマウスを乗せたときの反応
- タップした瞬間の反応
- 選択中タブの見た目
この3つを全部 :hover で片付けようとすると、タッチ端末で状態が混ざりやすくなります。
特に「押したあとも :hover の見た目が残る」と、今選ばれている .is-active の見た目 と競合しやすくなります。
「タップした瞬間だけ」なら :active
タップした瞬間だけ反応して、指を離したら戻したいなら、基本は :active を使います。
.tab-button:active {
opacity: 0.7;
}
:active は「押している間だけ」なので、タップ後に残り続けません。
ただし、これは 選択状態 を表すものではありません。
タブが選ばれたままの見た目は、.is-active のようなクラスで持つ方が安定します。
:hover は hover できる端末だけに限定する
タッチ端末で :hover を残したくないなら、いちばん安全なのは hover を hover 可能端末だけに限定すること です。
@media (any-hover: hover) {
.tab-button:hover {
opacity: 0.7;
}
}
これなら、マウスのある端末では :hover が効き、タッチ中心の端末では不要な hover 演出を避けやすくなります。
実務での役割分担
タブやボタンでは、状態を次のように分けると整理しやすいです。
-
:hoverPC のホバー反応 -
:activeタップ / クリックの瞬間反応 -
.is-active選択中・開いている状態 -
:focus-visibleキーボード操作時の見た目
例:
.tab-button.is-active {
background: #333;
color: #fff;
}
@media (any-hover: hover) {
.tab-button:hover {
opacity: 0.7;
}
}
.tab-button:active {
opacity: 0.7;
}
.tab-button:focus-visible {
outline: 2px solid #333;
outline-offset: 2px;
}
このように分けると、PC / タッチ / キーボードの役割が重なりにくくなります。
Sass の mixin にするなら
同じパターンを繰り返すなら、Sass 側で hover 用とタッチ用を分けておくと便利です。
// iPhone などのタッチ端末では、:hover 相当の見た目がタップ後も残ることがある
@mixin hover-opacity($opacity: 0.6, $duration: 0.4s) {
transition: opacity $duration;
&:hover {
opacity: $opacity;
}
}
// ホバーのスタイルを継続させないため、any-hover: hover に限定し、タッチデバイス向けに :active を追加
@mixin tab-hover-opacity($opacity: 0.6, $duration: 0.4s) {
transition: opacity $duration;
@media (any-hover: hover) {
&:hover {
opacity: $opacity;
}
}
&:active {
opacity: $opacity;
}
}
この考え方なら、
- 通常リンクやPC向け演出は
hover-opacity - タブやタッチ端末を意識するボタンは
tab-hover-opacity
と使い分けやすくなります。
まとめ
iPhone で :hover がタップ後も残るのは、Safari がタップを hover 相当として扱うことがあるためです。
そのため、タブ切り替えやボタンでは次の整理が有効です。
:hoverは@media (any-hover: hover)で限定する- タップ瞬間だけの反応は
:active - 選択状態は
.is-active - キーボード操作は
:focus-visible
:hover だけで全部を表現しようとせず、「マウス」「タップ」「選択状態」を分ける と、タッチ端末でも挙動が安定しやすくなります。