リアルタイム検証
メールアドレスを入力すると形式を即時判定し、✓(緑)/ ✗(赤)とメッセージでフィードバックする。
プレビュー
操作実際に入力して試せます。
使いどころ
入力ルールが機械的に判定できる項目(メールアドレスの形式、郵便番号の桁数など)に向く。この実装はメールの正規表現チェックのみを対象にしており、値が入るたびに即座に ✓/✗ を出す。フォーム送信前に体裁の誤りだけでも早期に気づかせたい場面で有効だが、「そのメールアドレスが実在するか」「そのユーザー名が空いているか」のようにサーバーに問い合わせないと判定できない項目には向かない。この実装のようにキー入力ごとに毎回判定する設計は、メールアドレスをまだ途中まで(taro@ex)しか打っていない段階でも✗が出るため、タイピング中は常に赤く表示され続けることになる。ユーザーが打ち終わるまで待つ体験にしたいなら、初回はblur(フォーカスが外れたとき)まで判定を保留し、一度エラーを出した後だけ入力毎に再評価する設計に切り替えるべきである。
仕組み
input要素にinputイベントを1つ張り、validate() が空値・OK・NG の3状態を input.className の付け替え(無印/ok/err)と #iv-msg のテキスト差し替えで表現する。正規表現は /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/ で、@の前後に空白と@を含まない文字列があり、ドット以降に2文字以上あることだけを見る簡易チェックである。アイコンは span.iv-icon の textContent を "✓"/"✗" に差し替えるが、色だけは icon.style.color でJSから直接指定しており、input や msg のように CSS クラス切り替えでは統一されていない。これは実装上の非対称で、デザイントークンを変更する際に border-color や msg の色は CSS 側で一括管理できるのに、アイコンの色だけ JS 内の文字列を直す必要がある。
実装の注意
最大の注意点は、input イベントで毎回 validate() を呼ぶため、1文字打つごとに正規表現評価とDOM書き換えが走ること自体は軽量だが、これを将来「サーバーにユーザー名の重複確認をする」ような非同期処理に置き換えると、キー入力のたびにリクエストが飛んでしまう。デバウンス(300〜500ms程度の遅延)を入れずに非同期化するのは典型的な失敗である。次に、アイコンの色を icon.style.color で直接指定している箇所は、CSSのテーマ変更(ダークモード対応など)で見落とされやすい。CSS変数や .ok/.err クラスをアイコン側にも付与して一元管理する方が保守しやすい。また正規表現は形式チェックに過ぎず、実在しないドメインや意図的なタイポ(gmial.comなど)は素通りするため、「✓が出た=正しいメールアドレス」という過信をユーザーにもコードにも持たせてはいけない。
アクセシビリティ
#iv-msg は状態が変わるたびにテキストが変わるが aria-live 属性が無いため、スクリーンリーダー利用者はメッセージの変化を自動的には聞き取れず、フィールドを離れて別の場所を能動的に探索しない限り「正しい形式です」も「形式で入力してください」も読み上げられない。aria-live="polite" を #iv-msg に付けるのが最小限の修正になる。またinput要素自体に aria-invalid の切り替えが無く、aria-describedby で #iv-msg と関連付けてもいない。視覚的にはボーダー色とアイコンとメッセージの3つで状態を示しており、色だけに頼っていない点は良い設計だが、これらの視覚情報がスクリーンリーダーには一切伝わらない構造になっているため、aria-invalid="true/false" と aria-describedby="iv-msg" の追加が本質的に必要である。アイコンの span には aria-hidden="true" が付いており、装飾要素として正しく除外されている点は評価できる。
調整して使う
判定タイミングは「毎キー入力」「blur時のみ」「初回はblur・以降は毎キー入力」の3パターンが考えられ、後者2つの方が実運用では好まれる。エラー時のメッセージ表示を aria-live="assertive" にして送信失敗時のみ強く割り込ませ、通常の入力中フィードバックは "polite" に留めるという使い分けも可能。同じ「入力欄+アイコン+メッセージ」の骨格は、パスワード強度メーターや郵便番号形式チェックなど他のフィールドにも転用でき、正規表現とメッセージ文言だけを差し替える関数として切り出すと複数フィールドで再利用しやすくなる。✓表示についても、ユーザーがフィールドを離れる(blur)まで正解を確定表示しない設計にすると、ドメイン部分を打ち終える前に緑になってしまう「早すぎる正解表示」を避けられる。
コード(コピーして使えます)
<div class="iv-wrap">
<label class="iv-label" for="iv-email">メールアドレス</label>
<div class="iv-field">
<input
id="iv-email"
class="iv-input"
type="text"
placeholder="example@mail.com"
autocomplete="off"
/>
<span class="iv-icon" aria-hidden="true"></span>
</div>
<p class="iv-msg" id="iv-msg"></p>
</div>