:hover の仕組み
:hover は、マウスポインターが要素の上にある間、その要素に一致する疑似クラスです。任意のセレクタに付けて、ホバー状態のスタイルを書きます:
変わるのは :hover ルールの宣言だけで、それ以外は .btn から引き継がれます。ポインターが離れると、要素は通常のスタイルに戻ります。
transition でなめらかなホバー効果
通常の ルール (:hover ルールではなく) に transition を追加しない限り、ホバーの変化は一瞬で切り替わります。通常のルールに書けば、入るときも出るときもアニメーションします:
アニメーションさせるのにいちばん軽いプロパティは transform と opacity です。周りの要素を動かしません。width、height、margin をアニメーションさせると、フレームごとにページのリフローが起きます。所要時間、遅延、イージングは CSS transition のページ で解説しています。
リンクの色: :link、:visited、:hover、:active
リンクには昔からの 4 つの状態と、キーボードフォーカスがあります。ルールの順番が重要です:
| 疑似クラス | 適用される条件 |
|---|---|
:link | まだ訪問していないリンク |
:visited | URL がブラウザの履歴にある |
:hover | ポインターが上にある |
:active | 押されている |
:focus-visible | キーボードでフォーカスされている |
これらはすべて詳細度が同じなので、2 つが一致したときは後のルールが勝ちます。訪問済みのリンクにホバーすると :visited と :hover の両方に一致し、:visited が最後にあるとホバーの色は表示されません。安全な順番は Link、Visited、Hover、Active (LVHA) です:
ページが閲覧履歴を読み取れないよう、ブラウザは :visited で変更できるものを制限しています。効くのは色に関係するプロパティ (color、background-color、border-color、outline-color など少数) だけで、スクリプトからは常に未訪問の値が見えます。
:active: 押されている状態
:active は要素が押されている間に一致します。少し動かすだけで、ボタンに押した手応えが生まれます:
親要素のホバーで子要素をスタイルする
ホバー状態は、ポインターの下にある要素とそのすべての祖先に属します。そのため .card:hover .title は、カードのどこかにホバーしたときにタイトルをスタイルします。同じ考え方で、隠れた要素を表示することもできます:
:focus-within の行は重要です。これがないと、Tab キーで Delete ボタンに移動したキーボード利用者は、見えないボタンを押すことになります。ホバーで表示する仕組みには、必ずフォーカスのルールを組み合わせましょう。
タッチスクリーンでのホバー
スマートフォンやタブレットには、要素の上に置いたままにできるポインターがありません。ほとんどのモバイルブラウザは最初のタップで :hover を適用し、別の場所をタップするまで維持するため、ホバーのスタイルが残ったままに見えることがあります。次の 2 つのルールで対処できます:
- コンテンツにたどり着く唯一の手段を
:hoverの後ろに置かない。ホバーで開くメニューは、クリックでも開くようにします。 - 純粋に装飾的なホバー効果は、本物のホバーができる端末かを確認するメディアクエリで囲みます:
@media (hover: hover) {
.card:hover { transform: translateY(-4px); }
}
よくある間違い
- コロンの前にスペースを入れる。
.btn :hoverは「.btnの中でホバーされた要素」という意味です。.btn:hoverと書きましょう。 :hoverルールにだけtransitionを書く。 入るときはアニメーションしますが、出るときはパッと戻ります。通常のルールに書きましょう。- リンクの順番を間違える。
:link、:visited、:hover、:activeの順を守ります。 - ホバーだけでフォーカスのスタイルがない。 キーボード利用者は
:hoverを発生させません。操作できる要素には:focus-visibleのスタイルも付けましょう。 - 別の要素に覆われた要素へのホバー。 見えないオーバーレイ (よくあるのは absolute の疑似要素) がポインターを受け取ってしまうことがあります。オーバーレイに
pointer-events: noneを指定すれば直ります。
よくある質問
CSS でホバー効果を付けるには?
セレクタの後に :hover を付けたルールを書きます: .btn:hover { background: #1d4ed8; }。ポインターが要素の上にある間、宣言が適用されます。変化をアニメーションにするには、通常のルールに transition: background 0.2s; を追加します。
:hover と :active の違いは何ですか?
:hover はポインターが要素の上にある間に適用されます。:active は要素が押されている間、つまりマウスボタンを押してから離すまでに適用されます。押されているボタンは、ふつう hover と active の両方の状態にあります。
リンクの疑似クラスはどの順番で書けばいいですか?
:link、:visited、:hover、:active の順です (LVHA、英語では "LoVe HAte" と覚えます)。詳細度が同じなので後のルールが勝ちます。ほかの順番では、visited や hover のスタイルが hover や active のスタイルを隠してしまうことがあります。
CSS でリンクの色を変えるには?
a 要素をスタイルします: a { color: #2563eb; }。ほかの状態には a:visited { color: #7c3aed; } と a:hover { color: #1d4ed8; } を書きます。a に color を指定すれば、未訪問と訪問済みの両方のリンクに効きます。
スマホでも hover は効きますか?
タッチスクリーンには、要素の上に置いたままにできるポインターがありません。ほとんどのモバイルブラウザはタップ時に :hover を適用し、別の場所をタップするまで維持するため、ホバーのスタイルが残ったままになることがあります。ホバーだけの効果は @media (hover: hover) で囲み、大事なコンテンツをホバーの後ろに隠さないでください。