マウスを乗せても色が変わらないボタンの原因|CDN版Tailwindは独自クラスのhover用CSSを作らない仕様と、見た目で気づけない不具合を検出する方法
マウスを乗せても色が変わらないボタンの原因|CDN版Tailwindは独自クラスのhover用CSSを作らない仕様と、見た目で気づけない不具合を検出する方法
ボタンやメニューにマウスを乗せても色が変わらない。HTMLには hover:text-accent のようにホバー用のクラスがきちんと書いてある。打ち間違いもない。それでも何も起きない。
Tailwind CSSをCDN(scriptタグ1行で読み込む方式)で使っていて、accent のように自分で決めた名前のクラスでこの症状が出ているなら、最初に疑うべき原因は1つです。
accent のような独自の名前がTailwindのテーマに登録されていないため、hover:text-accent に対応するCSSがそもそも1行も生成されていない、です。
優先順位で負けているのでも、キャッシュが残っているのでもありません。クラス名はHTMLに付いているのに、それを受け取るCSSがこの世に存在しない状態です。この記事では、先に結論として原因の確かめ方と直し方を示し、そのあとで弊社の制作現場で実測した数字、そして「画面を見ても気づけないこの種の不具合を、機械的に洗い出す方法」をまとめます。
結論:直し方は3つ。どれか1つに統一する
CDN版Tailwindで独自の色やサイズをホバーに使いたいときは、次のどれかで書きます。
| 方法 | 書き方の例 | 向いている場面 |
|---|---|---|
| ① テーマに色を登録する | 設定に accent を追加し、hover:text-accent をそのまま使う |
同じ色をサイト全体で何十回も使う |
| ② 任意値の記法で書く | hover:text-[color:var(--color-accent)] |
数か所だけ・設定を触りたくない |
| ③ 素のCSSで書く | .nav a:hover { color: var(--color-accent); } |
Tailwindに頼らず確実に効かせたい |
①の登録は、バージョン3系のCDN(cdn.tailwindcss.com)なら次のように書きます。
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: { extend: { colors: { accent: 'var(--color-accent)' } } }
}
</script>
これで text-accent bg-accent border-accent と、その hover: focus: md: 付きの形がすべて生成対象になります。バージョン4系のブラウザ版を使っている場合は、<style type="text/tailwindcss"> の中の @theme に --color-accent を定義する方式に変わっています。自分のサイトがどちらを読み込んでいるかは、HTMLの <script src> を見れば分かります。
大事なのは「混ぜない」ことです。書き方が混在していると、効く箇所と効かない箇所が同じサイトに並び、いちばん見つけにくくなります。
なぜ起きるのか:自分で書いた .text-accent と、Tailwindの hover: は別物
この症状が起きるサイトには、共通の作りがあります。ブランドカラーをCSS変数で持ち、それを使うクラスを自分のCSSに書いている構成です。
:root { --color-accent: #b08d57; }
.text-accent { color: var(--color-accent); }
.bg-accent { background-color: var(--color-accent); }
class="text-accent" と書けば、ちゃんとアクセントカラーになります。これは自分のCSSが効いているからです。ここで多くの人が、「text-accent が使えるのだから、hover:text-accent も使えるはず」と考えます。Tailwindの他の色、たとえば hover:text-blue-600 は普通に動くので、なおさらそう見えます。
ところが、この2つは仕組みがまったく違います。
text-accent… 自分のCSSファイルに書いた、ただのクラス。Tailwindは関与していないhover:text-accent… Tailwindが「text-accentというユーティリティ」を知っている場合にだけ、Tailwindが生成するクラス
CDN版Tailwindは、ページ内に書かれたクラス名を読み取り、自分が知っているユーティリティに該当するものだけ、その場でCSSを生成します。accent という色がテーマに無ければ、text-accent はTailwindにとって未知の文字列です。未知の文字列に hover: が付いていても、何も生成しません。エラーも警告も出ません。
hover: は「Tailwindのユーティリティの前に付ける接頭辞」であって、「任意のクラスにホバーを足す機能」ではないからです。
1分で確かめる方法
ブラウザの開発者ツール(ChromeならF12、MacはCommand+Option+I)で、色が変わらない要素を右クリックして「検証」を開きます。Stylesパネル上部の「:hov」を押して :hover にチェックを入れ、強制的にホバー状態にします。
- ホバー用の指定が一覧に出てきて、打ち消し線が付いている → 別の指定に優先順位で負けています。こちらは別記事「CSSが一部だけ効かないときに見るところ」の範囲です
- ホバー用の指定が一覧のどこにも出てこない → CSSが存在しません。この記事の症状です
なお、修正したCSS全体が反映されていない場合は配信元やキャッシュの問題で、これは「WordPressでCSSを直したのに反映されないとき」にまとめています。今回の症状は「他は全部効いているのに、ホバーだけ何も起きない」のが特徴です。
実測:見た目が正常なサイトで、38箇所のホバー指定にCSSが無かった
弊社が美容室向けに使っているサイトのひな形で、実際にこの状態を実測したことがあります。ある美容室サイトの公開前検証で、読み込まれているスタイルシートを機械的に走査したところ、次の結果が出ました。
| HTMLに書かれていたクラス | 箇所数 | 対応するCSS |
|---|---|---|
hover:text-accent |
30 | なし |
hover:bg-accent |
3 | なし |
hover:border-accent |
5 | なし |
hover:bg-[color:var(--color-accent)](任意値の記法) |
1種類 | あり |
合計38箇所のホバー指定に、CSSが1行も存在していませんでした。生成されていたのは、任意値の記法で書かれた1種類だけです。
この結果が示しているのは、この不具合の性質です。
- 表示は一切崩れない。 通常時の色も、レイアウトも、スマホ表示も正常。足りないのは「マウスを乗せたときの変化」だけ
- 一部は効いている。 任意値の記法で書いたボタンは正しく反応するため、「ホバーは動いている」という印象が残る
- スマホでは確認できない。 タッチ端末にホバーは無いので、スマホ中心の確認では永久に見つからない
- エラーが出ない。 Consoleは静かなまま
つまり、目視のチェックでは構造的に見つけられません。ひな形に入っていた書き方なので、同じひな形から作ったサイトにも同じ状態が引き継がれている可能性が高くなります。1サイトで見つけたら、同じ元から作った他のサイトも点検対象に入れるのが正しい進め方です。
実害は「ホバーの反応が無い」だけで、予約や問い合わせができなくなる類の不具合ではありません。ただ、パソコンで見ている人にとって、マウスを乗せても反応しないリンクは「押せるのかどうか分からない」要素です。メニューや予約ボタンで起きていれば、直す価値は十分にあります。
もう1つの原因:JavaScriptが色を直接書き込んでいる要素
CSSを正しく生成させても、まだ効かない要素が残ることがあります。先ほどの実例でも、ヘッダーのメニューがそうでした。
スクロールに応じてヘッダーの文字色を白から黒へ切り替える、といった動きをJavaScriptで実装しているサイトでは、スクリプトが element.style.color = '#fff' のようにインラインスタイルで色を書き込んでいます。インラインスタイルは、!important の付いていないクラス指定よりも優先されます。hover:text-accent のCSSが正しく存在していても、インラインの色に上書きされて見た目は変わりません。
開発者ツールで見ると、こちらは「ホバー用の指定が一覧に出てくるが、打ち消し線が付いている。勝っているのは element.style」という形で現れます。対処は2つです。
- ホバー時の色もJavaScript側で切り替える(
mouseenter/mouseleave) - CSS側で
#site-header nav a:hover { color: var(--color-accent) !important; }のように!importantで押し返す
!important は多用すると保守が苦しくなりますが、「インラインスタイルに勝つ」という目的に限っては正当な使い方です。
見た目で判断しない:効いていない指定をConsoleで一括検出する
ここまでの話で分かるとおり、この種の不具合は「見て確認する」方法では漏れます。確実なのは、HTMLで使われているクラスと、実際に存在するCSSルールを突き合わせることです。
開発者ツールのConsoleに次のスクリプトを貼り付けて実行すると、hover: focus: や md: などの接頭辞付きクラスのうち、対応するCSSが見つからないものが一覧で出ます。
const used = new Set();
document.querySelectorAll('[class]').forEach(el =>
el.classList.forEach(c => {
if (/^(hover|focus|active|group-hover|sm|md|lg|xl):/.test(c)) used.add(c);
})
);
const selectors = [];
const walk = rules => {
for (const r of rules) {
if (r.selectorText) selectors.push(r.selectorText);
if (r.cssRules) walk(r.cssRules);
}
};
for (const sheet of document.styleSheets) {
try { walk(sheet.cssRules); } catch (e) { /* 別ドメインのCSSは読めない */ }
}
const all = selectors.join('\n');
const missing = [...used].filter(c => !all.includes(CSS.escape(c)));
console.table(missing);
使うときの注意が3つあります。
- ページの読み込みが終わってから実行する。 CDN版TailwindはページのHTMLを見てからCSSを生成するため、読み込み直後だと生成前の状態を見てしまいます
- 別ドメインから読み込んでいるCSSは中身を読めない。 ブラウザの制約で、その分は検査対象から外れます。Tailwindが生成したCSSはページ内の
<style>に入るので、今回の目的には支障ありません - 結果が0件でも「全部正しい」とは限らない。 このスクリプトが見ているのは「ルールが存在するか」だけです。前述のインラインスタイルに負けているケースは検出できないので、ヘッダーなどJavaScriptが色を触っている箇所は、開発者ツールの「:hov」で個別に確認します
一覧に出てきたクラスが、直す対象です。同じクラス名が何十箇所にあっても、テーマ登録(①の方法)なら設定を数行足すだけで全部まとめて直ります。任意値の記法(②)に書き換える場合は、エディタの一括置換で hover:text-accent → hover:text-[color:var(--color-accent)] のように置き換えます。
制作を依頼する側が知っておくとよいこと
店舗オーナーやWEB担当者の立場で、この話から持ち帰れる点を3つ挙げます。
公開前の確認はパソコンでも行う。 スマホでの確認は必須ですが、スマホだけでは「マウスを乗せたときの反応」は絶対に確認できません。納品前チェックでは、パソコンのブラウザでメニュー・ボタン・リンクに実際にマウスを乗せ、色や下線が変わるかを見てください。変わらないものがあれば、制作側に「ホバーの指定が効いているか確認してほしい」と伝えれば足ります。
CDN版のTailwindは、本来は試作用。 Tailwindの公式ドキュメントでも、scriptタグで読み込む方式は開発・試作向けと位置づけられています。小規模な店舗サイトで使うこと自体は現実的な選択ですが、ページを開くたびにブラウザ側でCSSを生成する方式であること、そして今回のように「書いたつもりの指定が黙って無視される」余地があることは、制作側と共有しておくとよい前提です。長く運用するサイトなら、ビルドして静的なCSSにする構成への切り替えを検討する価値があります。
ひな形から作ったサイトは、ひな形ごと点検する。 テンプレートを元に複数のサイトを作っている場合、1つのサイトで見つかった不具合は、同じ元から作った他のサイトにもある前提で考えます。表示が崩れない不具合は、誰からも指摘されないまま残り続けます。
まとめ
hover:text-accentのような独自名のホバーが効かないのは、その名前がTailwindのテーマに無く、CSSが1行も生成されていないから。優先順位やキャッシュの問題ではない- 確かめ方は、開発者ツールの「:hov」でホバー状態にして、指定が一覧に出てくるかを見る。出てこなければこの症状
- 直し方は ①テーマに登録 ②任意値の記法 ③素のCSS のどれか。サイト内で混ぜない
- JavaScriptがインラインで色を書いている要素は、CSSが正しくても効かない。ホバーもJavaScriptで扱うか、
!importantで押し返す - この不具合は表示が崩れず、スマホでは再現せず、エラーも出ない。目視ではなく、使われているクラスと実在するCSSルールの突き合わせで検出する
「見た目に問題が無い」ことと「書いた指定が効いている」ことは別です。接頭辞付きのクラスを多用しているサイトほど、一度Consoleで突き合わせてみることをおすすめします。