メールアドレスの入力ミスを防ぐため、「メールアドレス」と「確認用メールアドレス」を2回入力させるフォームは一般的です。この記事ではリアルタイム一致チェック・ペースト禁止・フォーム送信制御・UX設計のベストプラクティスまで解説します。
この記事でわかること
- 2つの入力欄がリアルタイムで一致しているかチェックする
- 確認欄へのペーストを禁止する(手入力を強制)
- 一致していない場合はフォーム送信をブロックする
- メールアドレスの形式バリデーションと組み合わせる
- 確認欄不要論と現代のUXベストプラクティス
リアルタイム一致チェックの基本実装
<input type="email" id="email" placeholder="メールアドレス"> <input type="email" id="email-confirm" placeholder="メールアドレス(確認)"> <p id="email-error" style="color:red"></p>
$(function () {
function checkMatch() {
var email = $('#email').val();
var confirm = $('#email-confirm').val();
// 確認欄が空の間はエラーを表示しない
if (confirm === '') {
$('#email-error').text('');
return;
}
if (email !== confirm) {
$('#email-error').text('メールアドレスが一致しません');
} else {
$('#email-error').text('');
}
}
// 両方の入力欄の変更を監視
$('#email, #email-confirm').on('input', checkMatch);
});
確認欄が空の間はエラーを出さない
ユーザーが確認欄を入力し始める前にエラーを表示すると、混乱を招きます。確認欄に1文字以上入力されてから比較するのがUXのベストプラクティスです。
ユーザーが確認欄を入力し始める前にエラーを表示すると、混乱を招きます。確認欄に1文字以上入力されてから比較するのがUXのベストプラクティスです。
確認欄へのペースト禁止
手打ちを強制することで、コピペによる同じタイポを2回繰り返すミスを防ぎます。
$(function () {
// 確認欄へのペースト・ドラッグ&ドロップを禁止
$('#email-confirm').on('paste drop', function (e) {
e.preventDefault();
$('#email-error').text('確認欄には直接入力してください');
});
});
ペースト禁止はUX議論あり
ペースト禁止はパスワードマネージャーを使えなくするなど、アクセシビリティ上の問題があります。WCAG 2.1のガイドラインでも、フォームフィールドへのペーストを禁止しないよう推奨しています。「確認欄不要論」とあわせて、本当に必要か要件を確認してください。
ペースト禁止はパスワードマネージャーを使えなくするなど、アクセシビリティ上の問題があります。WCAG 2.1のガイドラインでも、フォームフィールドへのペーストを禁止しないよう推奨しています。「確認欄不要論」とあわせて、本当に必要か要件を確認してください。
フォーム送信時の一致チェックとブロック
$(function () {
$('form').on('submit', function (e) {
var email = $('#email').val();
var confirm = $('#email-confirm').val();
if (email !== confirm) {
e.preventDefault(); // 送信をブロック
$('#email-error').text('メールアドレスが一致しません').show();
$('#email-confirm').focus(); // 確認欄にフォーカス
return;
}
$('#email-error').hide();
});
});
メール形式バリデーションと組み合わせる
function isValidEmail(str) {
// 簡易的なメール形式チェック
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(str);
}
$(function () {
$('form').on('submit', function (e) {
var email = $('#email').val();
var confirm = $('#email-confirm').val();
var errors = [];
if (!isValidEmail(email)) {
errors.push('メールアドレスの形式が正しくありません');
}
if (email !== confirm) {
errors.push('メールアドレスが一致しません');
}
if (errors.length > 0) {
e.preventDefault();
$('#email-error').html(errors.join('<br>')).show();
} else {
$('#email-error').hide();
}
});
});
メール形式チェックはサーバー側でも行う
クライアント側のバリデーションはUX改善が目的です。悪意あるユーザーはJavaScriptをバイパスできるため、サーバー側でも必ずメールアドレスの形式チェックと送達確認を行ってください。
クライアント側のバリデーションはUX改善が目的です。悪意あるユーザーはJavaScriptをバイパスできるため、サーバー側でも必ずメールアドレスの形式チェックと送達確認を行ってください。
確認欄不要論とモダンなUX設計
| 方法 | メリット | デメリット |
|---|---|---|
| 確認欄あり(従来型) | タイポを目視確認できる | 入力手間が2倍・離脱率増加・パスマネージャー非対応 |
| 確認欄なし+パスワード表示ボタン | 入力が1回で済む・UX改善 | タイポに自分で気づく必要がある |
| 確認メール送付 | 実際に届くかを確認できる | 確認メールの手間・迷惑メール問題 |
NNGroupの研究では確認欄はエラー率を下げない場合もあると報告されています。新規フォームでは「確認欄を省略して確認メールを送る」設計も検討してください。
まとめ
メールアドレス一致チェックの実装ポイントをまとめます。
- リアルタイムチェック: 確認欄が空の間はエラーを出さない
- ペースト禁止:
paste dropイベントでe.preventDefault() - 送信制御:
form submitで一致チェック → 不一致ならe.preventDefault() - 形式チェックと組み合わせてエラーをまとめて表示
- 確認欄が本当に必要か要件を見直すことも重要
関連記事: フォームバリデーション完全ガイド / ラジオボタンの操作完全ガイド / 文字数をカウントする完全ガイド
よくある質問(FAQ)
Q大文字・小文字を区別せずに比較したいです。
Aメールアドレスのローカルパート(@より前)は技術的には大文字小文字を区別しますが、実用上は区別しないサーバーがほとんどです。比較時に
email.toLowerCase() !== confirm.toLowerCase() とすると、ユーザーが誤って大文字で入力した場合でも一致と判定できます。Qタイプ中に一致・不一致を色で示したいです。
A確認欄の
input イベントで一致/不一致に応じてクラスを付け外しします:$(this).toggleClass("is-valid", email === confirm).toggleClass("is-invalid", email !== confirm && confirm !== "")CSSで .is-valid { border-color: green; } のようにスタイルを定義してください。Q確認欄だけでなく元の欄も変更された場合に再チェックしたいです。
A両方の入力欄に同じ関数をバインドします:
$("#email, #email-confirm").on("input", checkMatch)これで元のメール欄を修正した際にも確認欄との比較が再実行されます。本記事の基本実装がこのパターンです。Qオートフィルで両方の欄に同じ値が入りますがペースト禁止と競合しませんか?
Aブラウザのオートフィルは
paste イベントを発火させないため、オートフィルはペースト禁止の影響を受けません。ただし autocomplete="new-password" を設定するとオートフィルを抑制できます。QReact / Vue でも同じアプローチで実装できますか?
Aロジックは同じですが、状態管理をjQueryの直接DOM操作ではなくstateで行います。Reactなら
useState で2つのemailを管理し、render時に email !== confirm でエラーを表示します。バリデーションロジック自体は共通なのでユーティリティ関数として切り出せます。