【実務・中級編】 user-invalid疑似クラスによるバリデーション制御 – CSS実践ガイド

CSSの「:user-invalid」で、JavaScriptによるエラー制御の9割を捨て去ろう

フロントエンドの現場で「フォームバリデーション」という言葉を聞くと、反射的にJavaScriptのライブラリや複雑な状態管理を思い浮かべる人が多い。もちろん、複雑なビジネスルールを検証するにはJSが不可欠だ。しかし、メールアドレスの形式や必須チェックといった「ブラウザの標準機能で完結できるバリデーション」にまで、JSでガチガチに制御を入れようとしていないだろうか?

実は、CSSの `:user-invalid` を使いこなすだけで、ユーザー体験(UX)を劇的に向上させつつ、コードベースを驚くほどクリーンに保てる。今日は、私が長年現場で培ってきた「CSSによるバリデーション制御の極意」を伝授しよう。

—

なぜ `:invalid` ではなく `:user-invalid` なのか?

まず、基本のおさらいだ。CSSには昔から `:invalid` という疑似クラスが存在する。しかし、これを使ってエラーをハイライトすると、ある致命的な問題が起きる。

それは、「ページを開いた瞬間にエラーが表示される」という現象だ。

ユーザーはまだ入力すらしていないのに、必須項目のフォームが最初から真っ赤に染まっている。これではユーザーのやる気を削ぐどころか、単なる「脅し」に他ならない。

ここで登場するのが `:user-invalid` だ。この疑似クラスは、単に値が不正であるだけでなく、「ユーザーがそのフィールドを操作(入力・変更・フォーカスアウト)した後に」という文脈をブラウザ側で自動的に判定してくれる。ブラウザが裏側で「ユーザーの意図的な操作」を監視し、その結果として不正な状態である場合にのみマッチする。これが、真にモダンでUXを考慮したバリデーションの鍵だ。

—

実践:コピペですぐに使えるモダン・バリデーション

では、現場でそのまま使える実装例を見てみよう。重要なのは、HTML側の `required` や `type=”email”` といった属性を最大限活用することだ。

/ ベースとなる入力フィールドのスタイル /
.input-field {
padding: 10px;
border: 1px solid #ccc;
border-radius: 4px;
transition: border-color 0.2s ease;
}

/ ユーザーが入力した後にエラーがある場合のみ、枠線を赤くする /
.input-field:user-invalid {
border-color: #ff4d4f;
background-color: #fff2f0;
}

/ エラーメッセージを隣接セレクタで制御 /
.error-message {
display: none; / 初期状態は非表示 /
color: #ff4d4f;
font-size: 0.8rem;
margin-top: 4px;
}

/ :user-invalid にマッチした時だけエラーメッセージを表示させる /
.input-field:user-invalid + .error-message {
display: block;
}


有効なメールアドレスを入力してください。

—

ブラウザが裏でやっていること

この仕組みを支えているのは、ブラウザが持つ「状態マシン」だ。
ブラウザは以下の状態を内部的に管理している。

1. Constraint Validation API: HTML属性(`pattern`, `minlength`, `type` など)を元に、入力値が妥当かを判定する。
2. Interaction State: ユーザーがフィールドに対して「フォーカスして去った」か、「値を変更して去った」かを判定する。

`:user-invalid` は、これら2つの状態が「不正」かつ「ユーザーの操作後」である場合にのみ発火する。つまり、JSで `onBlur` イベントを一つひとつ登録し、stateを切り替えてクラスを付与する……といった、あの面倒な作業を全てブラウザのネイティブ機能に委譲できるということだ。

—

シニアエンジニアからのアドバイス:運用上の落とし穴

この手法は強力だが、実務では以下の2点に注意してほしい。

1. ブラウザのサポート状況:
現在、`:user-invalid` は主要ブラウザでサポートされているが、古い環境を考慮する必要がある場合は `:invalid` と併用するか、Polyfillを検討してほしい。しかし、モダンなWeb開発においては、もはや「使うべき標準機能」と言っていい。

2. アクセシビリティ(A11y)の確保:
CSSで表示を切り替えるだけでは、スクリーンリーダーにエラーの存在が伝わらない。本気でバリデーションを実装するなら、HTMLの `aria-invalid=”true”` をJSで制御する(あるいは `aria-describedby` でエラーテキストを紐付ける)ことは忘れないでくれ。

まとめ

フロントエンドのコードを綺麗に保つコツは、「CSSでできることをJSでやらないこと」に尽きる。

バリデーションのタイミング制御をCSSに任せることで、JSのロジックは「データの送信」や「複雑なドメインロジックの検証」といった、本来やるべき仕事に専念できる。コードが減れば、バグも減る。バグが減れば、心に余裕ができる。

さあ、明日のプルリクエストから、不要なバリデーション管理用のJSを少しずつ削っていこうじゃないか。

コメント

タイトルとURLをコピーしました