CSSを使用したフォームの有効・無効状態のスタイリング
ユーザーが1文字も入力する前から、空の必須フィールドが赤く光る。これは多くのフォームが提供する不快な体験ですが、モダンCSSを使えば完全に回避できます。
本ガイドでは、CSSフォーム検証状態とそれを制御する疑似クラスについて解説します。:validと:invalidをいつ使用すべきか、なぜ:user-validと:user-invalidがより良いUXを提供するのか、そして:has()などのパターンを使用して親要素をスタイリングする方法について学びます。
重要なポイント
- HTML5制約検証は
required、type、min、max、patternなどの属性で自動的に機能します - エラースタイリングには
:validと:invalidの使用を避けましょう。これらはユーザーの操作前に発動します :user-validと:user-invalidを使用して、ユーザーがフィールドを操作した後にのみ検証フィードバックを表示します:has()と検証疑似クラスを組み合わせて、親要素をスタイリングし、エラーメッセージの表示を制御します- 視覚的な検証は常にARIA属性と組み合わせて、スクリーンリーダーのアクセシビリティを確保しましょう
制約検証の仕組み
HTML5制約検証は自動的に行われます。フォームフィールドにrequired、type="email"、min、max、minlength、maxlength、patternなどの属性を追加すると、ブラウザは妥当性を継続的に評価します。
ブラウザは入力値が変更されるたびに制約をチェックします。CSS疑似クラスはこの妥当性状態をリアルタイムで反映し、検証の合否に基づいてフィールドをスタイリングできます。
<input type="email" required minlength="5" />
このフィールドは、空の場合、値がメール形式でない場合、または5文字未満の場合に無効になります。
CSSフォーム疑似クラスの基本
:validと:invalid
これらの疑似クラスは、現在の妥当性に基づいてフィールドにマッチします:
input:valid {
border-color: green;
}
input:invalid {
border-color: red;
}
問題点::invalidはページ読み込み時に即座に適用されます。値のない必須フィールドは、ユーザーが触れる前から技術的に無効です。これにより、ユーザーが何も間違ったことをしていないのにエラーが表示されるという悪い体験を生み出します。
:requiredと:optional
これらはrequired属性に基づいてフィールドをターゲットにします:
input:required {
border-left: 3px solid blue;
}
input:optional {
border-left: 3px solid gray;
}
どのフィールドが必須かを示す視覚的インジケーターとして有用です。
:in-rangeと:out-of-range
min/max制約を持つnumber型やrange型の入力に対して:
input:in-range {
background: white;
}
input:out-of-range {
background: #ffe0e0;
}
:user-validと:user-invalidによる優れたUX
:user-validと:user-invalid疑似クラスは、早すぎるエラー表示の問題を解決します。これらはユーザーがフィールドを操作した後にのみマッチします—通常は編集してフォーカスを外した後です。
input:user-invalid {
border-color: red;
}
input:user-valid {
border-color: green;
}
これで必須フィールドはページ読み込み時にエラーを表示しなくなります。検証スタイリングは、ユーザーがデータを入力する機会を得た後にのみ表示されます。これはユーザーの期待に合致し、フラストレーションを軽減します。
これらの疑似クラスは幅広いブラウザサポートがあり、CSSでフォームエラーをスタイリングする際のデフォルトの選択肢とすべきです。
Discover how at OpenReplay.com.
:has()による親要素のスタイリング
:has()セレクタは、子要素の検証状態に基づいて親要素をスタイリングすることを可能にします—これは以前はJavaScriptなしでは不可能でした。
<div class="field">
<label for="email">メールアドレス</label>
<input type="email" id="email" required />
<span class="error">有効なメールアドレスを入力してください</span>
</div>
.error {
display: none;
color: red;
}
.field:has(input:user-invalid) .error {
display: block;
}
.field:has(input:user-invalid) input {
border-color: red;
}
このパターンは、含まれる入力がユーザー操作後に検証に失敗した場合にのみエラーメッセージを表示します。親コンテナが兄弟エラー要素の表示を制御します。
アクセシビリティの考慮事項
視覚的なスタイリングだけでは、アクセシブルなフォームには不十分です。スクリーンリーダーのユーザーには、プログラム的なエラーの関連付けが必要です。
CSS検証状態を適切なARIA属性と組み合わせましょう:
<div class="field">
<label for="email">メールアドレス</label>
<input
type="email"
id="email"
required
aria-describedby="email-error"
aria-invalid="false"
/>
<span id="email-error" class="error" aria-live="polite">
有効なメールアドレスを入力してください
</span>
</div>
主要なアクセシビリティ要件:
- **
aria-describedby**は入力をエラーメッセージにリンクします - **
aria-live="polite"**はエラーの変更をスクリーンリーダーに通知します - **
aria-invalid**は検証が失敗したときにJavaScriptで更新する必要があります - 色のコントラストはWCAG要件(テキストで4.5:1)を満たす必要があります
- 色だけに依存しない—色の変化と併せてアイコンやテキストを使用します
実践的パターン:完全なフィールド検証
これらのテクニックを組み合わせた、本番環境対応のパターンを紹介します:
/* 基本フィールドスタイル */
.field input {
border: 2px solid #ccc;
transition: border-color 0.2s;
}
/* 操作後の有効状態 */
.field:has(input:user-valid) input {
border-color: #2e7d32;
}
/* 操作後の無効状態 */
.field:has(input:user-invalid) input {
border-color: #c62828;
}
.field:has(input:user-invalid) .error {
display: block;
}
/* エラーメッセージはデフォルトで非表示 */
.error {
display: none;
color: #c62828;
font-size: 0.875rem;
margin-top: 0.25rem;
}
このアプローチは、ユーザーがフィールドを操作するまでエラーメッセージを非表示にし、検証が失敗した場合にのみ表示します。
まとめ
モダンCSSのフォーム疑似クラスは、JavaScriptなしで強力な検証スタイリングを提供します。主要なツールとして:user-validと:user-invalidを使用しましょう—これらは早すぎるエラー表示を防ぎ、ユーザーの期待に合致します。:has()と組み合わせて、エラーメッセージの表示を制御する親レベルのスタイリングを実現できます。
視覚的なスタイリングは、アクセシブルなエラー処理を補完するものであり、置き換えるものではないことを忘れないでください。CSS検証状態は常に、スクリーンリーダーユーザー向けの適切なARIA属性と組み合わせましょう。
よくある質問
:invalid疑似クラスは、ページ読み込み時やユーザー操作前を含め、検証に失敗したすべてのフィールドにマッチします。:user-invalid疑似クラスは、ユーザーがフィールドを操作してフォーカスを外した後にのみマッチします。これにより、ユーザーが入力する機会を得る前に、空の必須フィールドにエラースタイルが表示されることを防ぎます。
これらの疑似クラスは、Chrome、Firefox、Safari、Edgeを含むモダンブラウザで幅広くサポートされています。古いブラウザのサポートが必要な場合は、フォールバックパターンとして:focusと:not(:placeholder-shown)疑似クラスの使用を検討してください。ただし、このアプローチは精度が低くなります。
CSS検証疑似クラスは、ブラウザの制約検証API状態を反映します。デフォルトのフォーム送信を防止したり、JavaScriptでフォームを処理する場合は、フォーム要素に対してcheckValidity()を呼び出すようにしてください。CSS状態は、送信試行ではなく、validityプロパティに基づいて更新されます。
親コンテナに:has()セレクタを使用して、子入力の検証状態を検出します。例えば、.field:has(input:user-invalid) .error-messageを使用すると、そのコンテナ内の入力がユーザー操作後に検証に失敗したかどうかに基づいて、兄弟エラー要素を表示または非表示にできます。
Truly understand users experience
See every user interaction, feel every frustration and track all hesitations with OpenReplay — the open-source digital experience platform. It can be self-hosted in minutes, giving you complete control over your customer data. . Check our GitHub repo and join the thousands of developers in our community..