「フォームに不正な値が入力されたらエラーを出したい」「送信ボタンを押す前にリアルタイムでチェックしたい」――そんな要件をjQueryで手軽に実装する方法を解説します。
この記事では手動実装とjQuery Validation Pluginの2通りを取り上げ、実務でそのまま使える完全サンプルコードを提供します。
この記事でわかること
- 必須・文字数・メール・パスワード強度チェックの実装方法
- blur / input イベントを使ったリアルタイムバリデーション
- jQuery Validation Plugin の基本と応用
- カスタムバリデーションルールの追加方法
- アクセシビリティ対応(aria属性)のポイント
重要: クライアントサイドのバリデーションはUXを向上させるものであり、セキュリティ対策にはなりません。悪意あるユーザーはブラウザのJavaScriptを無効化してフォームを送信できます。必ずサーバーサイドでも同様のバリデーションを実施してください。
手動でバリデーションを実装する
基本的なHTMLフォームの準備
まずバリデーション対象のフォームを用意します。エラーメッセージ表示用の <span> を各フィールドの直後に置くのが定番パターンです。
<form id="registForm" novalidate>
<div class="form-group">
<label for="username">ユーザー名 <span class="required">*</span></label>
<input type="text" id="username" name="username" autocomplete="username"
aria-describedby="username-error">
<span class="error-msg" id="username-error" role="alert"></span>
</div>
<div class="form-group">
<label for="email">メールアドレス <span class="required">*</span></label>
<input type="email" id="email" name="email" autocomplete="email"
aria-describedby="email-error">
<span class="error-msg" id="email-error" role="alert"></span>
</div>
<div class="form-group">
<label for="password">パスワード <span class="required">*</span></label>
<input type="password" id="password" name="password" autocomplete="new-password"
aria-describedby="password-error">
<span class="error-msg" id="password-error" role="alert"></span>
<div class="strength-bar"><div class="strength-fill" id="strength-fill"></div></div>
<span class="strength-label" id="strength-label"></span>
</div>
<button type="submit" id="submitBtn">登録する</button>
</form>
ポイントは以下の2点です。
novalidate属性を<form>に付けてブラウザ標準のバリデーションを無効化し、自前のエラー表示に統一するaria-describedbyでエラー要素と紐付けることでスクリーンリーダーにも伝わる
エラー表示のCSS
.form-group { margin-bottom: 1.2rem; }
.form-group input { display: block; width: 100%; padding: .5rem .75rem; border: 1px solid #ccc; border-radius: 4px; transition: border-color .2s; }
.form-group input.is-invalid { border-color: #e74c3c; }
.form-group input.is-valid { border-color: #27ae60; }
.error-msg { display: block; color: #e74c3c; font-size: .85rem; margin-top: .25rem; min-height: 1.1em; }
.required { color: #e74c3c; }
/* パスワード強度バー */
.strength-bar { height: 6px; background: #eee; border-radius: 3px; margin-top: .4rem; }
.strength-fill { height: 100%; border-radius: 3px; width: 0; transition: width .3s, background .3s; }
.strength-label { font-size: .8rem; margin-top: .2rem; }
バリデーション関数を定義する
各チェックロジックを関数に切り出しておくと、再利用・テストがしやすくなります。
// --- バリデーションルール定義 ---
// 必須チェック
function isRequired(val) {
return val.trim().length > 0;
}
// 文字数チェック
function isLengthBetween(val, min, max) {
const len = val.trim().length;
return len >= min && len <= max;
}
// メールアドレス形式チェック
function isEmail(val) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val.trim());
}
// パスワード強度スコア(0〜4)
function passwordScore(val) {
let score = 0;
if (val.length >= 8) score++; // 8文字以上
if (/[a-z]/.test(val)) score++; // 小文字含む
if (/[A-Z]/.test(val)) score++; // 大文字含む
if (/[0-9]/.test(val)) score++; // 数字含む
if (/[^a-zA-Z0-9]/.test(val)) score++; // 記号含む(最大5点に)
return Math.min(score, 4);
}
// エラー表示ユーティリティ
function showError($input, $msg, text) {
$input.addClass('is-invalid').removeClass('is-valid');
$msg.text(text);
}
function showValid($input, $msg) {
$input.addClass('is-valid').removeClass('is-invalid');
$msg.text('');
}
リアルタイムバリデーション(blur / input イベント)
blur イベントはフィールドからフォーカスが外れたとき、input イベントは文字入力のたびに発火します。両方を組み合わせることで「入力中はチェックしない、フォーカスを外したらチェック」という自然なUXになります。
$(function () {
// ===== ユーザー名 =====
$("#username").on("blur", function () {
const $el = $(this);
const $err = $("#username-error");
const val = $el.val();
if (!isRequired(val)) {
showError($el, $err, "ユーザー名は必須です。");
} else if (!isLengthBetween(val, 3, 20)) {
showError($el, $err, "3〜20文字で入力してください。");
} else {
showValid($el, $err);
}
});
// ===== メールアドレス =====
$("#email").on("blur", function () {
const $el = $(this);
const $err = $("#email-error");
const val = $el.val();
if (!isRequired(val)) {
showError($el, $err, "メールアドレスは必須です。");
} else if (!isEmail(val)) {
showError($el, $err, "正しいメールアドレスを入力してください。");
} else {
showValid($el, $err);
}
});
// ===== パスワード(input で強度を即時表示) =====
const strengthColors = ["#e74c3c", "#e67e22", "#f1c40f", "#2ecc71", "#27ae60"];
const strengthLabels = ["非常に弱い", "弱い", "普通", "強い", "非常に強い"];
$("#password").on("input", function () {
const val = $(this).val();
const score = passwordScore(val);
const pct = score * 25;
$("#strength-fill").css({ width: pct + "%", background: strengthColors[score] });
$("#strength-label").text(val ? "強度: " + strengthLabels[score] : "");
}).on("blur", function () {
const $el = $(this);
const $err = $("#password-error");
const val = $el.val();
if (!isRequired(val)) {
showError($el, $err, "パスワードは必須です。");
} else if (val.length < 8) {
showError($el, $err, "8文字以上で入力してください。");
} else if (passwordScore(val) < 2) {
showError($el, $err, "大文字・小文字・数字を組み合わせてください。");
} else {
showValid($el, $err);
}
});
// ===== 送信時に全フィールドを一括チェック =====
$("#registForm").on("submit", function (e) {
e.preventDefault();
// 各フィールドに blur をトリガーして全エラーを表示
$("#username, #email, #password").trigger("blur");
// is-invalid が残っていれば送信しない
if ($(".is-invalid").length === 0) {
alert("送信しました!(実際の処理に差し替えてください)");
} else {
// 最初のエラーフィールドにフォーカス
$(".is-invalid").first().focus();
}
});
});
jQuery Validation Pluginを使う方法
jQuery Validation Plugin(jquery.validate.js)はjQuery公式チームが開発したバリデーションライブラリです。少ないコードでリッチなバリデーションを実装できます。
読み込み
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.20.0/jquery.validate.min.js" crossorigin="anonymous"></script> <!-- 日本語メッセージ --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.20.0/localization/messages_ja.min.js" crossorigin="anonymous"></script>
基本的な使い方
HTMLのフィールドに class="required" などの属性を付けるか、JavaScriptでルールを定義します。
$(function () {
$("#registForm").validate({
// バリデーションルール
rules: {
username: {
required: true,
minlength: 3,
maxlength: 20
},
email: {
required: true,
email: true
},
password: {
required: true,
minlength: 8
}
},
// エラーメッセージ(省略すると messages_ja.js の日本語メッセージが使われる)
messages: {
username: {
required: "ユーザー名を入力してください。",
minlength: "3文字以上で入力してください。",
maxlength: "20文字以内で入力してください。"
},
email: {
required: "メールアドレスを入力してください。",
email: "正しい形式で入力してください。"
},
password: {
required: "パスワードを入力してください。",
minlength: "8文字以上で入力してください。"
}
},
// エラー要素のカスタマイズ
errorElement: "span",
errorClass: "error-msg",
errorPlacement: function (error, element) {
error.insertAfter(element);
},
// 送信成功時の処理
submitHandler: function (form) {
alert("送信しました!");
// form.submit(); // 実際の送信処理
}
});
});
カスタムバリデーションルールを追加する
$.validator.addMethod() を使うと独自ルールを定義できます。電話番号・郵便番号など標準ルールにないチェックに便利です。
// 郵便番号チェック(例: 123-4567 または 1234567)
$.validator.addMethod("zipcode", function(value, element) {
return this.optional(element) || /^\d{3}-?\d{4}$/.test(value);
}, "正しい郵便番号を入力してください(例: 123-4567)");
// 電話番号チェック
$.validator.addMethod("phone", function(value, element) {
return this.optional(element) || /^0\d{1,4}-\d{1,4}-\d{4}$/.test(value);
}, "正しい電話番号を入力してください(例: 03-1234-5678)");
// 使い方(rulesの中で指定)
// zipcode: { required: true, zipcode: true }
応用:debounceでAjax重複チェックを実装する
「ユーザー名がすでに使われていないか」などのサーバー問い合わせをinputイベントに入れると、キー入力のたびにリクエストが飛びサーバーに負荷がかかります。debounce(入力停止後N ms後に実行)で抑制するのが定番パターンです。
// debounce ユーティリティ
function debounce(fn, delay) {
let timer;
return function () {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, arguments), delay);
};
}
// ユーザー名の重複チェック(入力停止から500ms後にサーバーへ問い合わせ)
$("#username").on("input", debounce(function () {
const val = $(this).val().trim();
if (val.length < 3) return; // 短すぎる場合はスキップ
$.ajax({
url: "/api/check-username",
method: "GET",
data: { username: val },
success: function (res) {
const $el = $("#username");
const $err = $("#username-error");
if (res.exists) {
showError($el, $err, "このユーザー名はすでに使われています。");
} else {
showValid($el, $err);
}
},
error: function () {
// 通信エラーは無視(サーバーサイドで最終チェックするため)
}
});
}, 500));
debounceのdelayについて: 300〜500ms が一般的です。短すぎると連続リクエストが発生し、長すぎるとユーザーが待たされます。500ms程度がUXと負荷のバランスが良いとされています。
手動実装 vs jQuery Validation Plugin 比較
| 項目 | 手動実装 | jQuery Validation Plugin |
|---|---|---|
| コード量 | 多い | 少ない |
| 依存ライブラリ | jQueryのみ | jQuery + プラグイン |
| カスタマイズ性 | 自由度が高い | addMethodで拡張可能 |
| 標準バリデーション | 自前で実装 | 豊富なルールが内蔵 |
| 日本語メッセージ | 自前で書く | localizationファイルで対応 |
| 学習コスト | 低い(jQuery知識のみ) | 少し学習が必要 |
| おすすめ用途 | シンプルなフォーム・フルコントロールしたい場合 | 複雑なフォーム・開発速度優先 |
よくあるトラブルと解決策
| 症状 | 原因 | 解決策 |
|---|---|---|
| 送信してもバリデーションが動かない | submitハンドラが複数登録されている、またはjQueryの読み込み前にコードが実行されている | $(document).ready() または $(function(){}) でラップする。ハンドラが重複していないか確認する |
| エラーメッセージが表示されない | エラー要素のセレクタが間違っている | $(‘#field-error’) のIDが実際のHTMLと一致しているか確認する |
| blurで動かない | ラジオ・チェックボックスはblurが発火しない | changeイベントを使う |
| プラグインの日本語メッセージが出ない | localizationファイルの読み込み漏れ、または読み込み順序が逆 | jQuery → jquery.validate.js → messages_ja.js の順に読み込む |
| 動的に追加したフィールドがバリデーションされない | 初期化後に追加した要素はプラグインが認識していない | 要素追加後に validator.element(‘#newField’) を呼ぶか、フォームを再初期化する |
よくある質問(FAQ)
関連記事: 【jQuery】blur()でフォーカスが外れた瞬間に処理を実行する方法 / jQueryでselectタグの値とテキストを取得する完全ガイド
まとめ
jQueryフォームバリデーションのポイント
- blur / input イベントでリアルタイムチェックを実現する
- エラー要素は
aria-describedbyで紐付けてアクセシビリティを確保する - 複雑なフォームはjQuery Validation Pluginで効率化できる
- カスタムルールは
$.validator.addMethod()で追加できる - クライアントサイドのバリデーションだけに頼らず、サーバーサイドでも必ず検証する
jQueryのバリデーションはUX改善の基本テクニックです。手動実装でしくみを理解した上で、必要に応じてjQuery Validation Pluginを使い分けてください。
