:has() で必須フォームのエラー演出
CSS :has() セレクタを活用し、HTML5 の :valid / :invalid 疑似クラスとと組み合わせて、JavaScript ゼロでフォーム入力状態に応じた装飾・送信ボタンの活性化を実現する。
解説
:has() で必須フォームのエラー演出は、便利系カテゴリの「has-selector」に分類される実装パターンです。CSS のみで構成され、難易度は中級レベル。
HTML5 標準の :valid / :invalid 疑似クラスと :has() セレクタを組み合わせると、JavaScript を一切書かずに「入力状態に応じてフォーム全体の装飾を変える」ことができます。
このサンプルでは、各フィールドのバリデーション状態に応じて緑(OK)/ 赤(NG)に切り替え、すべての必須項目が valid のときだけ送信ボタンを活性化する処理を、純粋な CSS だけで実装しています。React や Vue のフォームライブラリを使わない静的ページでも、UX の高いフォームを作れます。
仕組み
下記コードタブから HTML / CSS をそれぞれ確認・コピーできます。プレビュー領域では実際の動作をその場で確認可能です。
CSS プロパティだけで完結しているため、フレームワーク非依存・軽量に組み込めます。React / Vue / Astro / 静的 HTML どれにも持ち込み可能です。
注意点 / カスタマイズ時のポイント
:placeholder-shown を使って「未入力状態は invalid 表示しない」工夫をしています。プレースホルダー(placeholder=" " の半角スペース)が必須なので、HTML 側を必ず合わせてください。
JavaScript なしで送信処理を完全に止めることはできないので、サーバーサイドでの最終バリデーションは別途必須です。
よくある質問
JavaScript でカスタムバリデーション(パスワード強度など)を入れたい場合は?
:invalid は HTML5 標準の required / type="email" / minlength / pattern のみ反応します。独自ルールは JS で setCustomValidity() を呼び出すと :invalid に組み込めます。送信ボタンに :has() を使う部分の意味は?
:invalid の入力が含まれていない」状態のときだけ送信ボタンを活性化する条件です。.hf:not(:has(input:invalid)) button と書いています。このスニペットは商用利用できますか?
そのまま貼り付ければ動きますか?
ブラウザ対応は?
Tailwind CSS でも実装できますか?
@apply や arbitrary values が必要な場合があります。