
CSS疑似クラスでJavaScript代用、状態監視の全貌とevent-triggerの将来像
CSSは状態を追跡するための仕組みを着実に増やしている。かつてはJavaScriptでしか扱えなかったUIの変化を、疑似クラスだけで表現できる場面が広がっているのだ。
:hoverや:focusといった基本的なものから、:autofillや:volume-lockedのような新しい疑似クラスまで、その数は増え続けている。これらをJavaScriptイベントリスナーと比較しながら整理すると、CSSの設計思想がより明確に見えてくる。
ポインター系疑似クラス、UI反応の基本

マウスやタッチ操作に反応する疑似クラスは、ウェブデザインの基本だ。:hoverはpointerenterからpointerleaveまでの継続的な状態を表し、:activeは押下中の瞬間を捉える。これらは単なる一時的な出来事ではなく、ブラウザが認識する「状態」として設計されている。
:hoverと:activeの本質
CSS-Tricksの著者Carlo Daniele氏は、疑似クラスが「イベントではなく状態を追跡する」点を強調している。:hoverはpointerenterとpointerleaveという2つのJavaScriptイベントの間を継続的に監視する状態であり、:activeはpointerdownとpointerupの間の押下状態だ。この違いを理解すると、CSSとJavaScriptの適切な役割分担が明確になる。
上記のデモは静的な比較だが、実際の:hoverはカーソルが要素に乗っている間だけ継続する。JavaScriptではpointerenterとpointerleaveを個別に監視する必要があるが、CSSなら1行のセレクタで完結する。この簡潔さがCSSの強みだ。
pointer-eventsプロパティで反応を制御する
pointer-events: noneを指定すると、その要素はポインター関連のイベントを一切発火しなくなる。CSSで直接イベントの発生を抑制できる点は、JavaScriptでpreventDefaultを行うのとは異なる設計思想だ。装飾的なオーバーレイや無効化されたボタンなど、視覚的に存在するが操作対象ではない要素に有効な手法である。
フォーカス系疑似クラス、アクセシビリティの根幹

フォーカス管理はユーザビリティとアクセシビリティの両面で重要だ。CSSの疑似クラスは、JavaScriptのfocus/blurイベントよりも直感的にフォーカス状態をスタイリングできる。
:focusと:focus-visibleの使い分け
:focusは要素がフォーカスを受け取った瞬間に発動するが、マウス操作でもキーボード操作でも一律に適用される。一方、:focus-visibleはブラウザのヒューリスティック(経験則)に基づき、フォーカスインジケーターを表示すべきかどうかを判断する。キーボード操作時にはアウトラインを表示し、マウスクリック時には非表示にする、といった制御がCSSだけで可能だ。
JavaScriptで同等の処理を書く場合、:focus-visible疑似クラスをmatchMediaで問い合わせる必要があるが、CSSならセレクタに:focus-visibleを追加するだけで済む。コード量の差は一目瞭然である。
:focus-withinと:has()の比較
:focus-withinは子孫要素がフォーカスを持っている場合に、親要素をスタイリングできる。フォーム全体をハイライトしたいときに便利だ。:has(:focus)も機能的には同等だが、:has()はより汎用的な「条件付き親セレクタ」として設計されており、フォーカス以外の条件にも対応できる。どちらを使うかは文脈次第だが、フォーカス特化の:focus-withinのほうが意図は明確になる。
このように、子要素のフォーカス状態を親要素のスタイルに反映させる仕組みは、JavaScriptでDOMトラバーサルを書くよりも圧倒的にシンプルだ。
フォーム系疑似クラス、バリデーションをCSSで扱う

フォームの入力チェックはウェブ開発の定番だが、CSSの疑似クラスを使えば、視覚的なフィードバックの大部分をJavaScriptなしで実装できる。:validや:invalidはもちろん、:user-validや:autofillといった新しい疑似クラスも登場している。
:checkedで切り替えUIを実装する
:checkedはチェックボックスやラジオボタンの選択状態を追跡する。JavaScriptのchangeイベントと異なり、CSSセレクタとしてスタイルに直接結びつく。CSS-Tricksの著者Carlo Daniele氏も指摘しているように、CSS疑似クラスは多くの場合、2つのJavaScriptイベントの間の状態を表現するが、時には条件分岐ロジックそのものを代替する。
この切り替えはJavaScriptのchangeイベントでcheckedプロパティを判定するのと同等だが、CSSではスタイルシート内のセレクタで完結する。コードの見通しが良くなる点が大きな利点だ。
:user-validと:autofill、ユーザー体験を高める新しい疑似クラス
:validや:invalidはページ読み込み直後から評価されるため、未入力の必須フィールドが即座に赤く表示される問題があった。:user-validと:user-invalidは、ユーザーが実際に値を入力しフォーカスを外すまで評価を遅延させる。JavaScriptのchangeイベントに近い挙動だ。
:autofillはブラウザの自動入力機能を検出するJavaScriptイベントが存在しない中で、CSSだけで自動入力されたフィールドをスタイリングできる貴重な手段である。パスワードマネージャーによる自動入力を視覚的に識別したい場合に実用的だ。
JavaScriptで同等の処理を実装する場合、checkValidity()メソッドやValidityStateオブジェクトを使うことになる。フォーム送信時に全体を検証するケースではJavaScriptが適しているが、入力中のリアルタイムフィードバックはCSSの疑似クラスに任せるほうが合理的だ。
メディア要素疑似クラス、動画と音声の状態をスタイリングする

HTML5の<audio>要素や<video>要素は、これまでJavaScriptで状態を監視しなければカスタムコントロールを作成できなかった。しかし、CSSのメディア要素疑似クラスが整備されつつあり、状況は変わりつつある。これらの疑似クラスはInterop 2026の対象にもなっており、ブラウザ間の相互運用性の向上が期待されている。
:volume-lockedは特に興味深い。JavaScriptで音量ロックを検出するには、ダミーのvideo要素を生成してvolumeを設定し、その値が反映されたかどうかを確認するという回りくどい方法が必要になる。CSSなら:volume-locked疑似クラスひとつで完結する。ブラウザ側の制約をCSSが抽象化してくれる好例だ。
インタラクティブ要素疑似クラス、ポップオーバーとダイアログの制御

近年HTMLに追加された<dialog>要素やポップオーバー機能は、CSSの疑似クラスと組み合わせることで真価を発揮する。:popover-open、:open、:modal、:fullscreenといった疑似クラスは、JavaScriptのtoggleイベントに頼らずにUIの状態をスタイリングできる。
JavaScriptで同様の処理を書く場合、toggleイベントを監視してから要素のopenプロパティをチェックする2段階の処理が必要になる。CSSの疑似クラスなら、スタイルシート内で直感的に記述できる。モーダルダイアログが開いているときに背景を暗くする処理も、:modal疑似クラスと::backdrop疑似要素の組み合わせで表現可能だ。
event-trigger、CSSに真のイベントリスナーが到来する未来

CSS-Tricksの著者Carlo Daniele氏が紹介しているAnimation Triggers仕様のevent-triggerは、現時点ではどのブラウザも未実装だが、CSSの状態監視を次の段階に引き上げる提案だ。これは従来の疑似クラスとは異なり、JavaScriptのイベントリスナーに近い働きをする。
event-triggerの基本構文
event-triggerは、CSSアニメーションを特定のイベントに結びつける仕組みである。event-trigger-nameでアニメーションの識別子を定義し、event-trigger-sourceで発火条件となるイベント(click、touch、dblclick、keypressなど)を指定する。アニメーションは通常その場で再生されるのではなく、イベントが発生するまで待機する。
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
}
button {
/* クリック時に --event アニメーションを発火 */
event-trigger: --event click;
}
div {
/* --event が発火したらアニメーションを前方再生 */
animation-trigger: --event play-forwards;
animation: fade-in 300ms both;
}この流れは、従来のCSS疑似クラスが「状態」を追跡していたのに対し、明らかに「イベント」の発生をトリガーとしている点が新しい。clickイベントは元に戻せない不可逆的な出来事だが、interestイベントのように出入りがあるイベントの場合は、ステートフルな双方向トリガーも定義できる。
ステートレスとステートフルの2種類のトリガー
event-triggerには2つのモードが想定されている。ステートレストリガーはclickのような一度きりのイベント向けで、アニメーションは一方向にのみ再生される。ステートフルトリガーはinterestのような持続的な関心を表すイベント向けで、イベントの開始と終了に応じてアニメーションを前後に再生できる。
/* ステートフルトリガーの例 */
button {
event-trigger: --event interest / interest;
}
div {
animation-trigger: --event play-forwards play-backwards;
animation: fade-in 300ms both;
}この構文では、interestの開始時にアニメーションを前方再生し、interestの終了時に逆再生する。ホバーでメニューがスライドインし、カーソルが離れるとスライドアウトするようなUIを、JavaScriptのイベントリスナーなしで実装できる可能性がある。
この仕様が実用化されれば、CSSのみで完結するUIコンポーネントの幅は大幅に広がるだろう。ただし、Carlo Daniele氏自身も記事内で触れているように、仕様は現在編集中であり、今後のドラフトで構成が大きく変わる可能性がある。現時点では構想段階の提案として捉えておくのが適切だ。
この記事のポイント
- CSS疑似クラスはJavaScriptイベントの代替ではなく、状態を監視する独自のレイヤーとして進化している
- :hoverや:focusのような基本疑似クラスから、:autofillや:volume-lockedのような新しい疑似クラスまで、対応範囲は拡大中
- メディア要素疑似クラスはInterop 2026の対象であり、ブラウザ間の相互運用性が今後向上する
- event-trigger仕様はCSSに真のイベントリスナーをもたらす提案だが、現時点では未実装であり将来の動向に注目すべき
- CSSとJavaScriptは競合するものではなく、適材適所で組み合わせることで効率的なUI開発が可能になる

・ 複数業界における17年間のデジタルビジネス開発経験
・ ウェブサイト開発のためのHTML、PHP、CSS、JavaScript等の実用的知識
・ 15ヶ国語対応の多言語SaaSの開発経験
・ 17年間にも及ぶ、Eコマース長期運営経験
・ 幅広い業界でのSEO最適化の豊富な経験
