Tailwind CSSでhoverが効かない原因と対処|v4のタッチデバイス問題を解決

Tailwind v4のhover判定フロー。マウス主体のPCではhoverが効き、タッチ対応ノートPCではChromiumの誤判定でhoverが効かなくなる
  • このエントリーをはてなブックマークに追加

スポンサーリンク

「昨日まで効いていた hover: が、Tailwind CSS を v4 に上げたら急に効かなくなった」——そんな経験はありませんか? ボタンにマウスを乗せても色が変わらない。でもコードは間違っていない。実はこれ、あなたのミスではなく Tailwind v4 の仕様変更が原因です。しかも「特定のPCでだけ効かない」という、気づきにくい落とし穴が潜んでいます。

この記事では、v4 で hover が効かなくなる仕組みと、状況別の直し方を解説します。まず結論から。全デバイスで今までどおり hover を効かせたいなら、CSS に次の1行を足すだけです。

/* app.css など @import "tailwindcss" の後ろに書く */
@custom-variant hover (&:hover);

「なぜこれで直るのか」「もっと良い書き方はないのか」を、順を追って見ていきましょう。

なぜ v4 で hover が効かなくなったのか

Tailwind CSS v4 では、hover: ユーティリティが デフォルトで @media (hover: hover) というメディアクエリで囲まれるようになりました。実際に生成される CSS はこんなイメージです。

/* v4 が hover:bg-blue-600 から生成する CSS */
@media (hover: hover) {
  .hover\:bg-blue-600:hover {
    background-color: #2563eb;
  }
}

@media (hover: hover) は「マウスやトラックパッドなど、ホバー操作ができる入力機器を主に使っている端末」でだけ中身を適用する、という意味です。狙いは スマホ・タブレットでの「hover が張り付く」問題を防ぐこと。タッチ端末には本来ホバーの概念がなく、タップすると hover 状態が残ってしまう不具合がありました。v4 はこれを標準で回避してくれるようになったわけです。方向性としては正しい進化です。

本当のハマりポイントは「タッチ対応PC」

問題は、この判定が いつも正しいとは限らないことです。とくに次のような環境で、デスクトップなのに hover が効かなくなります。

  • タッチスクリーン搭載のノートPC(Windows の 2-in-1 など)
  • 外付けマウス・キーボードをつないだタブレットPC

これらの端末では、マウスをつないでいても Chromium 系ブラウザが「主な入力はタッチだ」と誤判定することがあります。すると @media (hover: hover)false になり、マウスがあるのに hover が一切効かないという状態に。開発している自分のPCだけで再現して、原因がわからず数時間溶かす——という典型的なハマりです。

Tailwind v4のhover判定フロー。マウス主体のPCではhoverが効き、タッチ対応ノートPCではChromiumの誤判定でhoverが効かなくなる
v4はhoverを「主な入力機器がホバー対応か」で判定する。タッチ対応PCは誤判定されやすい

「コードは正しいのに効かない」ときは、まず 自分のPCがタッチ対応かどうかを疑ってみてください。これが v3 にはなかった、v4 特有の新しい落とし穴です。

対処法①:全デバイスで hover を効かせる(一番シンプル)

「とにかく今までどおり、どの端末でも hover を効かせたい」なら、冒頭の1行が最短の解決策です。CSS のエントリーポイント(@import "tailwindcss" を書いているファイル)に、次のように追記します。

@import "tailwindcss";

/* hover をメディアクエリで囲まず、常に適用する */
@custom-variant hover (&:hover);

@custom-variant は v4 で追加された「バリアント(hover:focus: の部分)を自分で定義し直す」機能です。ここで hover&:hover だけの定義に上書きすると、@media (hover: hover) のラップが外れ、v3 までと同じ「常に効く hover」に戻ります。手っ取り早く直したいときはこれで十分です。

ただしこの書き方は、スマホでもタップ後に hover が残る問題が復活する点に注意してください。次に紹介する方法なら、そこもケアできます。

対処法②:any-hover でいいとこ取りする(おすすめ)

「マウスをつないだPCでは効かせたいが、スマホでは効かせたくない」——この両立を狙うなら、any-hover を使った定義がおすすめです。

@custom-variant hover {
  @media (any-hover: hover) {
    &:hover {
      @slot;
    }
  }
}

hover(デフォルト)が「主な入力機器がホバー対応か」を見るのに対し、any-hover は「いずれかの入力機器がホバー対応か」を見ます。マウスをつないだタッチ対応PCは「タッチもマウスもある」状態なので、any-hover: hover なら正しく true になり、hover が効きます。一方、マウスを一切持たない純粋なスマホでは false のまま。誤判定は避けつつ、スマホの張り付きも防げるバランスの良い書き方です。

@slot は、そのバリアントを付けたユーティリティの中身(この場合 hover:bg-blue-600background-color など)が展開される場所を表します。画面幅で切り替えたい場合は、メディアクエリを @media (width >= 768px) のように書き換えてもOKです。

対処法③:そもそも hover に依存しない(公式の推奨)

Tailwind 公式が最終的に推奨しているのは、hover を「あれば嬉しい装飾」として扱い、無くても成立するUIを設計するという考え方です。いわゆるプログレッシブ・エンハンスメントですね。

たとえば「hover で初めて表示される削除ボタン」は、タッチ端末では永遠に押せません。こういう UI は hover に頼らず、常に表示する・focus:active: でも反応させる、といった設計に変えるのが本質的な解決です。

<!-- hover だけに頼らず、focus/active でも反応させる -->
<button class="bg-blue-600 hover:bg-blue-700 focus:bg-blue-700 active:bg-blue-800">
  保存する
</button>

「重要な操作は hover 以外でも成立するか?」を一度チェックしておくと、端末を問わず使えるUIになります。急ぎなら①か②、腰を据えて直すなら③、と使い分けましょう。

group-hover・peer-hover も同じ影響を受ける

見落としがちですが、親要素にホバーしたら子が反応する group-hover: や、兄弟要素で連動する peer-hover: も、内部で hover を使うため まったく同じ理由で効かなくなります。対処も同じで、必要なバリアントを @custom-variant で上書きします。

/* group-hover も全デバイスで効かせたい場合 */
@custom-variant hover (&:hover);
@custom-variant group-hover (.group:hover &);

grouppeer の違いがあいまいな方は、Tailwind CSSのpeerとは?groupとの違いもあわせて読むと、どのバリアントを上書きすべきか判断しやすくなります。

hover 以外の「v4で急に効かない」あるある

v3 から v4 へ上げたとき、hover 以外にも「効かなくなった」と驚くポイントがあります。ハマりやすいものをまとめておきます。原因を知っていれば数分で直せます。

Tailwind v3からv4への移行で効かなくなりやすい5つの原因と対処のまとめ表
hover以外にも、v3→v4で「急に効かない」ポイントは押さえておくと数分で直せる
  • CSS の読み込み方が変わった@tailwind base; などの3行は廃止。@import "tailwindcss"; の1行に置き換えます。ここが古いままだと、そもそも何も効きません。
  • 枠線の色が変わったborder のデフォルト色が gray-200 から currentColor(文字色)に変更。border だけ書くと文字色の枠線になるので、border-gray-200 のように色を明示します。
  • ring が細く・色が変わったring の太さが 3px → 1px、色が blue-500currentColor に。v3 と同じ見た目にしたいなら ring-3 と色指定を使います。
  • 設定ファイルの場所が変わったtailwind.config.js ではなく CSS 内の @theme でカスタム値を定義します。config に書いた色やフォントが「効かない」のはこれが原因です。

これらは v4 の設計思想(設定を CSS に寄せ、デフォルトを素直にする)に沿った変更です。移行時は公式のアップグレードガイドを一度ざっと眺めておくと、こうした「効かない」を先回りで潰せます。

まとめ:hover が効かないときのチェックリスト

Tailwind v4 で hover が効かないときは、次の順で確認してみてください。

  • 自分のPCは タッチ対応ではないか?(Chromium が誤判定している可能性)
  • 急いで直すなら @custom-variant hover (&:hover); を1行足す
  • スマホの張り付きも防ぎたいなら any-hover 版を使う
  • 本質的には、重要な操作を hover に依存させない設計にする
  • group-hover / peer-hover も同じ対処が必要

「コードは正しいのに効かない」という理不尽の正体は、たいてい v4 の仕様変更です。原因さえ掴めば対処は一瞬なので、慌てず切り分けていきましょう。Tailwind の基本的な使い方をおさらいしたい方はTailwind CSSの使い方【初心者向け】、Rails への v4 導入はRailsにTailwind CSS v4を導入する方法@custom-variant をダークモードで使う例はTailwind CSSでダークモードを実装する方法も参考にしてください。

スポンサーリンク

  • このエントリーをはてなブックマークに追加