- HTML
HTMLフォームバリデーション|required・pattern早見表と完成例
HTML フォームバリデーションとは、required や pattern などの属性だけで、送信前に入力値をブラウザにチェックさせる仕組み(制約検証)です。 JavaScript なしでも動き、足りない部分は setCustomValidity() などの Constraint Validation API で補えます。
この記事では、属性と ValidityState のプロパティの対応表に加えて、Chromium 141(日本語ロケール)で実際に取得した既定のエラーメッセージ(validationMessage)の一覧を載せています。さらに、郵便番号・電話番号・全角カナ・半角英数・パスワードの pattern を実行して一致/不一致を確認した結果、checkValidity と reportValidity の違い、:invalid と :user-invalid の違いの実測、そして確認用パスワードの一致チェック付きで aria-describedby 対応のコピペ用完成フォームまで紹介します。
フォームバリデーションの早見表
| 属性・指定 | 何をチェックするか | 違反時の ValidityState | 既定メッセージ(Chromium 141・日本語) |
|---|---|---|---|
required |
空でないか | valueMissing |
このフィールドを入力してください。 |
required(checkbox) |
チェックされているか | valueMissing |
次に進むにはこのチェックボックスをオンにしてください。 |
required(select) |
空の value 以外を選んだか | valueMissing |
リスト内の項目を選択してください。 |
type="email" |
メール形式か | typeMismatch |
メール アドレスに「@」を挿入してください。「taro」内に「@」がありません。 |
type="url" |
URL 形式か | typeMismatch |
URL を入力してください。 |
type="number" に数値でない入力 |
数値として解釈できるか | badInput |
数字を入力してください。 |
pattern |
正規表現に全体一致するか | patternMismatch |
指定されている形式で入力してください。 |
minlength |
文字数の下限 | tooShort |
このテキストは 8 文字以上で指定してください(現在は 3 文字です)。 |
maxlength |
文字数の上限 | tooLong |
(通常は入力自体が止まるため発生しにくい) |
min |
下限値 | rangeUnderflow |
値は 1 以上にする必要があります。 |
max |
上限値 | rangeOverflow |
値は 10 以下にする必要があります。 |
step |
刻み | stepMismatch |
有効な値を入力してください。有効な値として最も近いのは 5 と 10 です。 |
type="date" + min |
日付の下限 | rangeUnderflow |
2026/10/01 以降の値を指定する必要があります。 |
setCustomValidity('…') |
独自ルール | customError |
指定した文字列がそのまま入る |
novalidate(form) |
フォーム全体の検証を省略 | — | — |
formnovalidate(button) |
そのボタンで送信するときだけ省略 | — | — |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「HTMLフォームバリデーション|required・pattern早見表と完成例」
制約検証の仕組み
ブラウザは送信時に各入力欄の制約をチェックし、1つでも違反があれば送信を止めて、最初の違反欄に吹き出しを表示します。 結果は各要素の validity(ValidityState オブジェクト)に入り、どの制約に違反したかが真偽値のプロパティで分かります。
flowchart LR
A[送信ボタン] --> B{form に novalidate? / ボタンに formnovalidate?}
B -- はい --> S[submit イベント → 送信]
B -- いいえ --> C[各入力欄の validity を確認]
C -- すべて valid --> S
C -- 違反あり --> D[違反欄で invalid イベント]
D --> E[最初の違反欄にフォーカス+吹き出し表示]
ValidityState のプロパティ一覧
| プロパティ | true になる条件 | 主な原因の属性 |
|---|---|---|
valueMissing |
必須なのに空 | required |
typeMismatch |
型の書式に合わない | type="email"、type="url" |
patternMismatch |
正規表現に合わない | pattern |
tooShort |
文字数が足りない(ユーザーが編集したときのみ) | minlength |
tooLong |
文字数が多すぎる(ユーザーが編集したときのみ) | maxlength |
rangeUnderflow |
下限より小さい | min |
rangeOverflow |
上限より大きい | max |
stepMismatch |
刻みに合わない | step |
badInput |
ブラウザが値に変換できない | type="number"、type="date" など |
customError |
setCustomValidity に空でない文字列を渡した |
JavaScript |
valid |
上のすべてが false | — |
検証の対象外になる要素
readonly・disabled・type="hidden" の要素は検証されません。 required を付けていても willValidate が false になります。
| 要素 | willValidate(実測) |
|---|---|
<input required readonly> |
false |
<input required disabled> |
false |
<input required type="hidden"> |
false |
<input required> |
true |
既定のエラーメッセージを実際に取得した一覧
検証環境:Python Playwright 1.56.0+Chromium 141.0.7390.37、--lang=ja、ロケール ja-JP。 各入力欄に値を入れて validity と validationMessage を取得しました。
| ケース | 入力値 | ValidityState | validationMessage |
|---|---|---|---|
required |
空 | valueMissing | このフィールドを入力してください。 |
type="email" |
taro |
typeMismatch | メール アドレスに「@」を挿入してください。「taro」内に「@」がありません。 |
type="email" |
taro@ |
typeMismatch | 「taro@」は完全なメールアドレスではありません。「@」に続く文字列を入力してください。 |
type="email" |
やまだ@example.com |
typeMismatch | 「@」の前の文字列に記号「や」を使用しないでください。 |
type="email" |
taro@example |
(違反なし) | — |
type="url" |
example.com |
typeMismatch | URL を入力してください。 |
type="number" |
1e / --1 / e と入力 |
badInput | 数字を入力してください。(value は空文字) |
pattern="\d{3}-\d{4}" |
1234567 |
patternMismatch | 指定されている形式で入力してください。 |
上に title="123-4567 の形式" を追加 |
1234567 |
patternMismatch | 指定されている形式で入力してください。(validationMessage には title は入らない) |
minlength="8" |
abc と入力 |
tooShort | このテキストは 8 文字以上で指定してください(現在は 3 文字です)。 |
type="number" min="1" |
0 |
rangeUnderflow | 値は 1 以上にする必要があります。 |
type="number" max="10" |
11 |
rangeOverflow | 値は 10 以下にする必要があります。 |
type="number" step="5" |
7 |
stepMismatch | 有効な値を入力してください。有効な値として最も近いのは 5 と 10 です。 |
type="date" min="2026-10-01" |
2026-09-30 |
rangeUnderflow | 2026/10/01 以降の値を指定する必要があります。 |
読み取れるポイント
type="email"はtaro@exampleのようにドットのないドメインも正しい形式として通します。 HTML の仕様どおりの動作です。ドット必須にしたい場合はpatternを追加します(メールアドレスの正規表現の詳細は別記事にまとめています)。type="number"に文字を入れると value は空文字になり、badInput が true になります。requiredを付けていなくても送信は止まります。- pattern の既定メッセージは「指定されている形式で入力してください。」だけで、どんな形式かは伝わりません。
titleは吹き出しの補足として表示されますが validationMessage には含まれないので、入力例は画面上のヒント文として出すのが確実です。 maxlengthは入力自体が止まります。 3文字制限の欄でefを追加入力しても value はabcのままでした。- メッセージの文言はブラウザや言語設定で変わります。画面に出す文言を統一したい場合は、後述の方法で独自メッセージに置き換えます。
pattern 属性の書き方と注意点
pattern は「値全体」に一致するかを見ます。 ブラウザが内部で ^(?: と )$ を補うので、自分で ^ $ を書く必要はありません。
Chromium 141 では pattern を v フラグ付きの正規表現としてコンパイルします。 そのため、文字クラスの中の - などの記号はエスケープが必要です。実際に [A-Za-z0-9-]+ を指定すると、パターンは無効になり、Console に次のメッセージが出て、どんな値も一致扱い(@@@ も通る)になりました。
Pattern attribute value [A-Za-z0-9-]+ is not a valid regular expression: Uncaught SyntaxError: Failed to read the 'patternMismatch' property from 'ValidityState': Invalid regular expression: /[A-Za-z0-9-]+/v: Invalid character class
| 書き方 | abc-1 |
@@@ |
状態 |
|---|---|---|---|
[A-Za-z0-9-]+ |
一致 | 一致 | パターン無効(検証されない) |
[A-Za-z0-9\-]+ |
一致 | 不一致 | 正しく動作 |
文字クラス内の - ( ) [ ] { } / | はバックスラッシュでエスケープすると、v フラグでもエラーになりません。pattern を書いたら Console にエラーが出ていないか確認すると安心です。
日本向け pattern 集(実行結果つき)
同じ環境で validity.patternMismatch を確認しました。「一致」は送信できる値です。
| 用途 | pattern | 一致 | 不一致 |
|---|---|---|---|
| 郵便番号(ハイフン任意) | \d{3}-?\d{4} |
123-4567、1234567 |
123-456、123-4567(全角)、123 4567 |
| 電話番号(ハイフン任意) | 0\d{1,4}-?\d{1,4}-?\d{4} |
03-1234-5678、0312345678、090-1234-5678、09012345678 |
+81-3-1234-5678、1234-5678 |
| 全角カナ(全角スペース可) | [ァ-ヶー ]+ |
ヤマダ タロウ、ヴァイオリン |
ヤマダ(半角)、やまだ、ヤマダ タロウ(半角スペース) |
| 半角英数 | [A-Za-z0-9]+ |
abc123、ABC |
abc-123、abc(全角) |
| パスワード(8〜64文字・英小文字・英大文字・数字を各1文字以上) | (?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\x21-\x7e]{8,64} |
Passw0rd、Passw0rd! |
password1、PASSWORD1、Pass0、Pass w0rd1(空白入り) |
電話番号の pattern は桁の組み合わせをゆるく見るだけです。厳密な番号体系のチェックはサーバー側で行い、フォームでは「入力ミスに早く気づいてもらう」程度にとどめると使いやすくなります。全角数字を受け付けたい場合は、pattern で弾くより、送信前に半角へ変換する方が親切です(value.normalize('NFKC') で全角英数字を半角にできます)。
<!-- そのまま使える入力欄の例 -->
<input name="zip" required pattern="\d{3}-?\d{4}" inputmode="numeric" autocomplete="postal-code">
<input name="tel" type="tel" pattern="0\d{1,4}-?\d{1,4}-?\d{4}" autocomplete="tel">
<input name="kana" required pattern="[ァ-ヶー ]+">
<input name="code" pattern="[A-Za-z0-9]+">
JavaScript で検証を制御する API
| API | 役割 | 戻り値・動作 |
|---|---|---|
el.validity |
違反の内容を見る | ValidityState |
el.validationMessage |
表示されるメッセージを取得 | 文字列(違反なしは空) |
el.willValidate |
検証の対象か | 真偽値 |
el.checkValidity() |
検証だけ行う | 真偽値。違反欄で invalid イベント |
el.reportValidity() |
検証して吹き出しを表示 | 真偽値。違反欄で invalid、最初の欄にフォーカス |
el.setCustomValidity(msg) |
独自エラーを設定 | 空文字で解除 |
form.requestSubmit() |
検証つきで送信 | form.submit() は検証も submit イベントもなし |
checkValidity と reportValidity の違い(実測)
required の入力欄を2つ持つフォームで、document に invalid イベントの数を数えるリスナー(capture)を付けて実行しました。
| 呼び出し | 戻り値 | invalid イベントの回数(累計) | フォーカス |
|---|---|---|---|
form.checkValidity() |
false | 2 | 移動しない(body のまま) |
続けて form.reportValidity() |
false | 4(+2) | 最初の違反欄に移動 |
どちらも違反しているすべての欄で invalid イベントが発生します。 違いは、reportValidity が吹き出しを出して最初の違反欄にフォーカスする点です。invalid イベントはバブリングしないので、form でまとめて受けたいときは addEventListener('invalid', fn, true) のように capture で登録します。
setCustomValidity は自分で解除するまで残る
a.setCustomValidity('NG');
a.validity.valid; // false
a.value = 'ok';
a.validity.valid; // false(値を変えても残る)
a.setCustomValidity('');
a.validity.valid; // true
上の3つの値は実測で [false, false, true] でした。setCustomValidity は値が変わっても自動では消えないため、input イベントのたびに条件を判定し、正しいときは必ず '' を渡します。これを忘れると、直したのに送信できない状態になります。
novalidate と formnovalidate(実測)
| フォームの書き方 | 空の required 欄で送信ボタンを押したとき |
|---|---|
| 通常 | submit イベントは発生しない(ブラウザが止める) |
<form novalidate> |
submit イベントが発生 |
<button formnovalidate> で送信 |
submit イベントが発生 |
formnovalidate は「下書き保存」ボタンなど、未入力でも送りたいボタンに付けます。 novalidate はブラウザの吹き出しを使わず、自前のエラー表示に切り替えるときに使います(ValidityState は novalidate でも使えます)。
:invalid と :user-invalid の違い
:invalid はページを開いた瞬間から一致するため、空の必須欄が最初から赤くなります。 :user-invalid は、ユーザーが操作した後や送信しようとした後にだけ一致します。
<input required minlength="3"> で状態ごとに matches() を確認した結果です。
| 状態 | :invalid |
:user-invalid |
|---|---|---|
| ページを開いた直後(空) | true | false |
フォーカスして x と入力中 |
true | false |
| 別の欄に移った(blur) | true | true |
xyz に直した |
false | false |
| 別のフォームで、空のまま送信ボタンを押した直後 | true | true |
入力欄を赤くするスタイルには :user-invalid を使うと、触る前から赤くなることがなく、送信しようとしたときには未入力欄も赤くなります。対になる :user-valid もあります。:user-invalid は Chrome 119、Firefox 88、Safari 16.5 以降で使えます。
/* 直す前:開いた瞬間から赤い */
input:invalid { border-color: #b00020; }
/* 直した後:操作した後や送信しようとした後だけ赤い */
input:user-invalid { border-color: #b00020; background: #fff5f5; }
input:user-valid { border-color: #1b7f3b; }
コピペ用完成フォーム(パスワード確認つき)
前提:HTML ファイル1つで動きます(外部ライブラリなし)。 全角カナの氏名、郵便番号、メールアドレス、パスワードと確認用パスワードを受け付けます。ブラウザの吹き出しの代わりに入力欄の下へエラーを表示し、aria-describedby でエラー文と入力欄を関連づけています。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>会員登録フォーム</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 480px; margin: 2rem auto; padding: 0 16px; }
.field { margin-bottom: 1.25rem; }
label { display: block; font-weight: 600; margin-bottom: .25rem; }
input { width: 100%; padding: .5rem; font-size: 1rem; border: 1px solid #888; border-radius: 4px; box-sizing: border-box; }
.hint { font-size: .85rem; color: #555; margin: .25rem 0 0; }
.error { font-size: .85rem; color: #b00020; margin: .25rem 0 0; min-height: 1.2em; }
/* 触る前は赤くしない::user-invalid を使う */
input:user-invalid { border-color: #b00020; background: #fff5f5; }
input:user-valid { border-color: #1b7f3b; }
button { padding: .6rem 1.5rem; font-size: 1rem; }
</style>
</head>
<body>
<h1>会員登録</h1>
<form id="signup" action="/signup" method="post" novalidate>
<div class="field">
<label for="name">氏名(全角カナ)</label>
<input id="name" name="name" required pattern="[ァ-ヶー ]+" autocomplete="name"
aria-describedby="name-hint name-error">
<p class="hint" id="name-hint">例:ヤマダ タロウ</p>
<p class="error" id="name-error" aria-live="polite"></p>
</div>
<div class="field">
<label for="zip">郵便番号</label>
<input id="zip" name="zip" required pattern="\d{3}-?\d{4}" inputmode="numeric"
autocomplete="postal-code" aria-describedby="zip-hint zip-error">
<p class="hint" id="zip-hint">例:123-4567(ハイフンなしも可)</p>
<p class="error" id="zip-error" aria-live="polite"></p>
</div>
<div class="field">
<label for="email">メールアドレス</label>
<input id="email" name="email" type="email" required autocomplete="email"
aria-describedby="email-error">
<p class="error" id="email-error" aria-live="polite"></p>
</div>
<div class="field">
<label for="password">パスワード</label>
<input id="password" name="password" type="password" required minlength="8" maxlength="64"
pattern="(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\x21-\x7e]{8,64}" autocomplete="new-password"
aria-describedby="password-hint password-error">
<p class="hint" id="password-hint">8〜64文字。英小文字・英大文字・数字をそれぞれ1文字以上</p>
<p class="error" id="password-error" aria-live="polite"></p>
</div>
<div class="field">
<label for="password2">パスワード(確認)</label>
<input id="password2" name="password2" type="password" required autocomplete="new-password"
aria-describedby="password2-error">
<p class="error" id="password2-error" aria-live="polite"></p>
</div>
<button type="submit">登録する</button>
</form>
<script>
const form = document.getElementById('signup');
const pw = document.getElementById('password');
const pw2 = document.getElementById('password2');
// 属性ごとの独自メッセージ(未指定のものはブラウザ既定の validationMessage を使う)
const messages = {
name: { valueMissing: '氏名を入力してください。', patternMismatch: '全角カタカナで入力してください。' },
zip: { valueMissing: '郵便番号を入力してください。', patternMismatch: '123-4567 の形式で入力してください。' },
email: { valueMissing: 'メールアドレスを入力してください。', typeMismatch: 'メールアドレスの形式で入力してください。' },
password: { valueMissing: 'パスワードを入力してください。', tooShort: '8文字以上で入力してください。',
patternMismatch: '英小文字・英大文字・数字をそれぞれ1文字以上含めてください。' },
password2:{ valueMissing: '確認用パスワードを入力してください。' },
};
function messageFor(input) {
const v = input.validity;
const m = messages[input.name] || {};
for (const key of ['valueMissing', 'typeMismatch', 'patternMismatch', 'tooShort', 'tooLong',
'rangeUnderflow', 'rangeOverflow', 'stepMismatch', 'badInput']) {
if (v[key]) return m[key] || input.validationMessage;
}
if (v.customError) return input.validationMessage;
return '';
}
function checkMatch() {
// 一致しないときだけ customError を立てる。一致したら必ず '' で解除する
pw2.setCustomValidity(pw2.value && pw.value !== pw2.value ? 'パスワードが一致しません。' : '');
}
function showError(input) {
const msg = messageFor(input);
const box = document.getElementById(input.id + '-error');
box.textContent = msg;
input.setAttribute('aria-invalid', msg ? 'true' : 'false');
}
pw.addEventListener('input', () => { checkMatch(); if (pw2.value) showError(pw2); });
pw2.addEventListener('input', checkMatch);
for (const input of form.querySelectorAll('input')) {
input.addEventListener('blur', () => showError(input)); // 離れたときに表示
input.addEventListener('input', () => { // 直したらすぐ消す
if (input.getAttribute('aria-invalid') === 'true') showError(input);
});
}
form.addEventListener('submit', (e) => {
checkMatch();
const inputs = [...form.querySelectorAll('input')];
inputs.forEach(showError);
const firstInvalid = inputs.find(i => !i.validity.valid);
if (firstInvalid) {
e.preventDefault();
firstInvalid.focus();
}
});
</script>
</body>
</html>
完成フォームの動作確認(Playwright+Chromium 141)
1. 何も入力せずに「登録する」を押した場合:送信されず、氏名欄にフォーカスが移りました。
| エラー欄 | 表示された文言 |
|---|---|
| name-error | 氏名を入力してください。 |
| zip-error | 郵便番号を入力してください。 |
| email-error | メールアドレスを入力してください。 |
| password-error | パスワードを入力してください。 |
| password2-error | 確認用パスワードを入力してください。 |
2. 誤った値で送信した場合(氏名 やまだ、郵便番号 123456、メール taro、パスワード password1、確認 password2):5欄すべてで aria-invalid="true" になりました。
| エラー欄 | 表示された文言 |
|---|---|
| name-error | 全角カタカナで入力してください。 |
| zip-error | 123-4567 の形式で入力してください。 |
| email-error | メールアドレスの形式で入力してください。 |
| password-error | 英小文字・英大文字・数字をそれぞれ1文字以上含めてください。 |
| password2-error | パスワードが一致しません。 |
3. 正しい値で送信した場合(ヤマダ タロウ、123-4567、taro@example.com、Passw0rd! を2回):エラー表示は空になり、/signup に POST が送られました。
POST /signup
name=%E3%83%A4%E3%83%9E%E3%83%80%E3%80%80%E3%82%BF%E3%83%AD%E3%82%A6&zip=123-4567&email=taro%40example.com&password=Passw0rd%21&password2=Passw0rd%21
このフォームの設計ポイント
| ポイント | 理由 |
|---|---|
novalidate + ValidityState で自前表示 |
文言を統一でき、吹き出しが消えても画面にエラーが残る |
| エラーは blur で表示し、input で消す | 入力中に急かさず、直したらすぐ反映される |
確認用パスワードは setCustomValidity |
他の制約と同じ validity.valid で一括判定できる |
一致したら setCustomValidity('') |
解除しないと送信できないまま残る |
送信時に最初の違反欄へ focus() |
キーボード操作やスクリーンリーダーでも位置が分かる |
autocomplete="new-password" |
パスワード管理ツールが強いパスワードを提案しやすくなる |
アクセシビリティ:エラーを支援技術に伝える
| 属性 | 役割 | 完成フォームでの使い方 |
|---|---|---|
<label for> |
入力欄の名前 | すべての欄に付ける |
aria-describedby |
補足説明とエラー文を関連づける | "zip-hint zip-error" のように空白区切りで複数指定 |
aria-invalid="true" |
入力に誤りがあることを伝える | エラー表示と同時に切り替え |
aria-live="polite" |
文言の変化を読み上げる | エラー表示用の <p> に付ける |
| 色以外の手がかり | 色だけに頼らない | 赤枠に加えてエラー文を表示 |
エラー文は「何が」「どう直せばよいか」まで書くと伝わりやすくなります。「入力が正しくありません」より「123-4567 の形式で入力してください。」の方が、一度で直せます。
サーバー側の検証も必須
HTML の制約検証は「入力ミスを早く知らせる」ための仕組みで、送信されるデータの安全を保証するものではありません。 開発者ツールで属性を外したり、curl などでフォームを通さずに直接 POST したりできるためです。
| 項目 | クライアント(HTML・JS) | サーバー |
|---|---|---|
| 目的 | 入力体験の向上、早期の気づき | データの正しさと安全の保証 |
| 回避できるか | できる(属性の削除、直接リクエスト) | できない |
| 必須チェック・形式チェック | 行う | 同じルールで必ず行う |
| 重複チェック(登録済みメールなど) | 補助的に(API で問い合わせ) | 行う |
| エラーの返し方 | 入力欄の下に表示 | 422 などで欄ごとのメッセージを返し、画面に反映 |
pattern の正規表現はサーバー側と共通の定義にしておくと、ルールのずれを防げます。サーバーからのエラーも、完成フォームの .error 欄と aria-invalid に流し込めば、同じ見た目で表示できます。
よくある質問
Q. ブラウザの吹き出しの文言だけを日本語の独自メッセージに変えられますか?
A. invalid イベントで setCustomValidity('独自の文言') を呼び、input イベントで setCustomValidity('') に戻すと変えられます。ただし解除を忘れると送信できなくなるため、本記事の完成フォームのように novalidate で自前表示にする方が管理しやすいです。
Q. pattern を指定したのに何を入れても通ります。
A. 正規表現が無効になっている可能性があります。 Chromium では pattern を v フラグでコンパイルするため、[A-Za-z0-9-] のように文字クラス内の - をエスケープしないと無効になります。Console のエラーを確認し、\- と書きます。
Q. :invalid と :user-invalid はどちらを使えばよいですか?
A. 見た目のエラー表示には :user-invalid が向いています。ページを開いた直後は一致せず、ユーザーが操作した後や送信しようとした後に一致します。
Q. type="email" でドットのないドメインが通ります。
A. HTML の仕様どおりです。ドット必須にしたい場合は pattern を併用し、最終的なチェックはサーバー側で行います。
まとめ
required・pattern・minlength・minなどの属性ごとに、ValidityState の対応するプロパティが true になります。- 既定のメッセージはブラウザと言語で変わるため、統一したい場合は
novalidateと ValidityState で自前表示にします。 - pattern は値全体に一致するかを見ます。 Chromium では v フラグでコンパイルされるので、文字クラス内の
-はエスケープします。 setCustomValidityは自分で''を渡すまで残ります。 確認用パスワードの一致チェックでは、一致したら必ず解除します。checkValidityは判定のみ、reportValidityは吹き出しとフォーカス移動つきです。どちらも違反欄で invalid イベントが発生します。- エラーの見た目には
:user-invalid、エラー文の関連づけにはaria-describedbyとaria-invalidを使います。 - HTML の検証は入力体験のため、サーバー側の検証は安全のためで、両方そろえて初めて完成です。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「HTMLフォームバリデーション|required・pattern早見表と完成例」
株式会社RJCでは、使いやすく正確な入力フォームの作り方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。