この記事では、HTMLフォームフィールドとHTML5が提供する検証オプションについて説明します。また、CSSやJavaScriptを使用してこれらを強化する方法についても説明します。
制約検証とは何ですか?
各フォームフィールドには目的があります。そして、この目的はしばしば制約によって管理されます。つまり、各フォームフィールドに入力すべきでないもののルールです。例えば、email
フィールドは有効なメールアドレスを要求し、password
フィールドは特定の種類の文字を要求し、最小の必要な文字数があります。そして、テキストフィールドには入力できる文字数に制限があります。
最新のブラウザには、これらの制約がユーザーによって遵守されているかを確認し、それらのルールが破られた場合に警告を発する機能があります。これを制約検証と呼びます。
クライアントサイド対サーバーサイドの検証
JavaScript言語の初期の年に書かれたほとんどのコードは、クライアントサイドのフォーム検証を処理していました。現在でも、開発者はフィールド値をチェックするための関数を書くために多くの時間を費やしています。現代のブラウザではこれはまだ必要ですか?おそらくそうではありません。ほとんどの場合、あなたが何をしようとしているかによって本当に依存します。
しかし、最初に大きな警告メッセージです:
クライアントサイドの検証は、アプリが時間と帯域幅を無駄にし、サーバーにデータを送信する前に一般的なデータ入力エラーを防ぐことができる親切です。サーバーサイドの検証の代わりにはなりません!
常にサーバーサイドでデータをサニタイズしてください。すべてのリクエストがブラウザから来るわけではありません。たとえそれがブラウザから来たとしても、ブラウザがデータを検証したという保証はありません。ブラウザの開発者ツールを知っている人は、あなたの愛情たっぷりのHTMLとJavaScriptをバイパスすることもできます。
HTML5入力フィールド
HTMLは次の機能を提供します:
<textarea>
複数行のテキストボックス用<select>
オプションのドロップダウンリスト用<button>
… ボタン用
しかし、最も頻繁に使用するのは<input>
です:
<input type="text" name="username" />
type
属性はコントロールのタイプを設定し、多くのオプションがあります:
type |
description |
---|---|
button |
a button with no default behavior |
checkbox |
a check/tick box |
color |
a color picker |
date |
a date picker for the year, month, and day |
datetime-local |
a date and time picker |
email |
an email entry field |
file |
a file picker |
hidden |
a hidden field |
image |
a button which displays the image defined by the src attribute |
month |
a month and year picker |
number |
a number entry field |
password |
a password entry field with obscured text |
radio |
a radio button |
range |
a slider control |
reset |
a button that resets all form inputs to their default values (but avoid using this, as it’s rarely useful) |
search |
a search entry field |
submit |
a form submission button |
tel |
a telephone number entry field |
text |
a text entry field |
time |
a time picker with no time zone |
url |
a URL entry field |
week |
a week number and year picker |
もしtype
属性を省略したり、サポートされていないオプションがあれば、ブラウザはtext
にフォールバックします。現代のブラウザはすべてのタイプをよくサポートしていますが、古いブラウザはまだテキスト入力フィールドを表示します。
他にも便利な<input>
属性には以下があります:
attribute | description |
---|---|
accept |
file upload type |
alt |
alternative text for the image types |
autocomplete |
hint for field auto-completion |
autofocus |
focus field on page load |
capture |
media capture input method |
checked |
checkbox/radio is checked |
disabled |
disable the control (it won’t be validated or have its value submitted) |
form |
associate with a form using this ID |
formaction |
URL for submission on submit and image buttons |
inputmode |
data type hint |
list |
ID of <datalist> autocomplete options |
max |
maximum value |
maxlength |
maximum string length |
min |
minimum value |
minlength |
minimum string length |
name |
name of control, as submitted to server |
pattern |
a regular expression pattern, such as [A-Z]+ for one or more uppercase characters |
placeholder |
placeholder text when the field value is empty |
readonly |
the field is not editable, but it will still be validated and submitted |
required |
the field is required |
size |
the size of the control (often overridden in CSS) |
spellcheck |
set true or false spell-checking |
src |
image URL |
step |
incremental values in numbers and ranges |
type |
field type (see above) |
value |
the initial value |
HTML出力フィールド
入力タイプだけでなく、HTML5は読み取り専用の出力も提供します:
output
: 計算やユーザー操作の結果として得られるテキスト出力progress
:value
およびmax
属性を持つプログレスバーmeter
:value
、min
、max
、low
、high
、およびoptimum
属性によって設定された値に応じて、グリーン、アンバー、レッドの間で変化するスケール
入力ラベル
フィールドには、関連付けられた<label>
が必要です。要素を囲むことができます:
<label>your name <input type="text" name="name" /><label>
または、フィールドのid
をfor
属性を使用してラベルにリンクします:
<label for="nameid">your name</label>
<input type="text" id="nameid" name="name" />
ラベルはアクセシビリティのために重要です。placeholder
を使用して画面スペースを節約するフォームに遭遇したことがあるかもしれません:
<input type="text" name="name" value="" placeholder="your name" />
プレースホルダテキストは、ユーザーが何かを入力すると(たとえそれが単一のスペースであっても)消えます。フィールドが何を求めているかをユーザーに覚えさせるよりも、ラベルを表示する方が良いです!
入力動作
フィールドタイプと制約属性は、ブラウザの入力動作を変えます。例えば、number
入力はモバイルデバイスで数値キーボードを表示します。フィールドはスピナーを表示し、キーボードの上下カーソル押下で値が増減します。
ほとんどのフィールドタイプは明らかですが、例外もあります。例えば、クレジットカードは数字ですが、増減スピナーは役に立たず、16桁の数字を入力する際に上下を押しやすいです。標準のtext
タイプを使用する方が良いですが、inputmode
属性をnumeric
に設定して、適切なキーボードを表示します。また、autocomplete="cc-number"
を設定することで、事前に設定されたまたは以前に入力されたカード番号を提案します。
適切なフィールドtype
とautocorrect
を使用することで、JavaScriptでは難しい利点が得られます。例えば、一部のモバイルブラウザでは次のようなことができます:
- カメラを使ってカードをスキャンしてクレジットカードの詳細をインポートする
- SMSで送られた一度きりのコードをインポートする
自動検証
ブラウザは、type
、min
、max
、step
、minlength
、maxlength
、pattern
、およびrequired
属性によって定義された制約に従って入力値を確認します。例えば:
<input type="number" min="1" max="100" required />
空の値を送信しようとすると、フォームの送信が阻止され、Chromeでは以下のメッセージが表示されます。
スピナーでは、1から100の範囲外の値を許可しません。数値でない文字列を入力すると、同様の検証メッセージが表示されます。すべてJavaScriptの1行も使わずに
ブラウザの検証を停止するには:
novalidate
属性を<form>
要素に追加するformnovalidate
属性を送信ボタンまたは画像に追加する
カスタムJavaScript入力の作成
新しいJavaScriptベースの日付入力コンポーネントを書いているなら、キーボードから手を離して立ち止まってください!
カスタム入力コントロールを作成することは難しいです。マウス、キーボード、タッチ、音声、アクセシビリティ、画面の寸法、そしてJavaScriptが失敗した場合に何が起こるかを考慮する必要があります。また、異なるユーザーエクスペリエンスを作成しています。おそらくあなたのコントロールはデスクトップ、iOS、Androidの標準の日付選択より優れていますが、慣れないUIは一部のユーザーを混乱させるでしょう。
開発者がJavaScriptベースの入力を作成する理由は主に3つあります。
1. 標準コントロールはスタイル付けが難しい
CSSスタイリングは限られており、入力をラベルの::before
および::after
疑似要素でオーバーレイするなどのハックが必要になることが多いです。状況は改善されていますが、機能よりフォームを重視するあらゆるデザインに疑問を呈してください。
2. 古いブラウザでは現代の<input>
タイプがサポートされていない
本質的には、Internet Explorer のためにコーディングしているのと同じです。IE ユーザーは日付ピッカーを取得できませんが、YYYY-MM-DD
形式で日付を入力できます。クライアントが固執する場合は、IE のみにポリフィルを読み込んでください。モダンブラウザに負担をかける必要はありません。
3. これまで実装されたことのない新しい入力タイプが必要です
これらの状況はまれですが、常に適切な HTML5 フィールドから始めてください。彼らは速く、スクリプトがロードされる前に動作します。必要に応じてフィールドを段階的に強化できます。たとえば、JavaScript のかけらを使って、カレンダーアドベントの終了日が開始日より後になるようにすることができます。
要約: HTML コントロールを再発明することを避ける!
CSS 検証スタイリング
次の擬似クラスを入力フィールドに適用して、現在の状態に応じてそれらをスタイルすることができます:
selector | description |
---|---|
:focus |
the field with focus |
:focus-within |
an element contains a field with focus (yes, it’s a parent selector!) |
:focus-visible |
an element has focus owing to keyboard navigation, so a focus ring or more evident styling is necessary |
:required |
a field with a required attribute |
:optional |
a field without a required attribute |
:valid |
a field that has passed validation |
:invalid |
a field that has not passed validation |
:user-valid |
a field that has passed validation after the user has interacted with it (Firefox only) |
:user-invalid |
a field that hasn’t passed validation after the user has interacted with it (Firefox only) |
:in-range |
the value is within range on a number or range input |
:out-of-range |
the value is out of range on a number or range input |
:disabled |
a field with a disabled attribute |
:enabled |
a field without a disabled attribute |
:read-only |
a field with a read-only attribute |
:read-write: |
a field without a read-only attribute |
:checked |
a checked checkbox or radio button |
:indeterminate |
an indeterminate checkbox or radio state, such as when all radio buttons are unchecked |
:default |
the default submit button or image |
入力のplaceholder
テキストを::placeholder
擬似要素でスタイルすることができます:
/* メールフィールドの青いプレースホルダー */
input[type="email"]::placeholder {
color: blue;
}
上記のセレクターは同じ特異性を持っているため、順序が重要な場合があります。次の例を考えてみましょう:
input:invalid { color: red; }
input:enabled { color: black; }
無効な入力は赤いテキストですが、disabled
属性を持つ入力にのみ適用されます— つまり、すべての有効な入力は黒です。
ブラウザはページの読み込み時に検証スタイルを適用します。たとえば、次のコードでは、すべての無効なフィールドに赤い境界線が与えられます:
:invalid {
border-color: #900;
}
ユーザーは、フォームと対話する前に、厳然とした赤いボックスのセットに直面しています。最初の送信後や値が変更されると検証エラーを表示すると、より良い体験が提供されます。そこでJavaScriptが登場します…
JavaScriptと制約検証API
制約検証APIは、標準のHTMLフィールドチェックを強化できるフォームカスタマイズオプションを提供します。以下のことができます:
- ユーザーがフィールドと対話するか、フォームを送信するまで検証を停止する
- カスタムスタイリングでエラーメッセージを表示する
- HTMLだけでは不可能なカスタム検証を提供する。これは、2つの入力を比較する必要がある場合によく必要になります。たとえば、メールアドレスや電話番号を入力するとき、「新規」と「確認」パスワードフィールドが同じ値であることを確認するか、1つの日付が別の日付より後であることを確認する場合などです。
フォーム検証
APIを使用する前に、コードはデフォルトの検証とエラーメッセージを無効にするために、フォームのnoValidate
プロパティをtrue
に設定する必要があります(novalidate
属性を追加するのと同じです):
const myform = document.getElementById('myform');
myform.noValidate = true;
次に、フォームが送信されたときなどのイベントハンドラーを追加できます:
myform.addEventListener('submit', validateForm);
ハンドラーは、checkValidity()
またはreportValidity()
メソッドを使用してフォーム全体が有効であるかを確認できます。これらは、フォームのすべての入力が有効な場合にtrue
を返します。(違いは、checkValidity()
が制約検証の対象となる入力があるかどうかを確認することです。)
Mozillaのドキュメント説明:
各無効なフィールドで
invalid
イベントがトリガーされます。これはバブリングしません: ハンドラはそれを使用する各コントロールに追加する必要があります。
// 送信時にフォームを検証する
function validateForm(e) {
const form = e.target;
if (form.checkValidity()) {
// フォームが有効 - さらなるチェックを行う
}
else {
// フォームが無効 - 送信をキャンセルする
e.preventDefault();
}
};
A valid form could now incur further validation checks. Similarly, an invalid form could have invalid fields highlighted.
フィールドの検証
個々のフィールドには以下の制約検証プロパティがあります:
-
willValidate
: 要素が制約検証の候補である場合true
を返します。 -
validationMessage
: 検証メッセージ。フィールドが有効な場合、これは空の文字列になります。 -
valitity
: フィールドが有効である場合、ValidityState オブジェクトのvalid
プロパティがtrue
に設定されます。無効の場合、false
の場合、以下のプロパティの1つ以上がtrue
になります:ValidityState 説明 .badInput
ブラウザが入力を理解できない .customError
カスタム有効性メッセージが設定されている .patternMismatch
値が指定された pattern
属性と一致しない.rangeOverflow
値が max
属性より大きい.rangeUnderflow
値が min
属性より小さい.stepMismatch
値が step
属性のルールに合わない.tooLong
文字列の長さが maxlength
属性を超えている.tooShort
文字列の長さが minlength
属性未満である.typeMismatch
値が有効なメールアドレスまたはURLでない .valueMissing
required
の値が空である
個々のフィールドは以下の制約検証メソッドを持っています:
setCustomValidity(message)
: 無効なフィールドにエラーメッセージを設定します。フィールドが有効な場合は空の文字列を渡さなければなりません。そうしないと、フィールドは永久に無効のままになります。checkValidity()
: 入力が有効な場合にtrue
を返します。valitity.valid
プロパティも同じことを行いますが、checkValidity()
はフィールド上でinvalid
イベントもトリガーするため便利です。
validateForm()
ハンドラ関数は、各フィールドをループし、必要な場合に親要素に invalid
クラスを適用することができます:
function validateForm(e) {
const form = e.target;
if (form.checkValidity()) {
// フォームが有効 - さらなるチェックを実行
}
else {
// フォームが無効 - 送信をキャンセル
e.preventDefault();
// invalid クラスを適用
Array.from(form.elements).forEach(i => {
if (i.checkValidity()) {
// フィールドが有効 - クラスを削除
i.parentElement.classList.remove('invalid');
}
else {
// フィールドが無効 - クラスを追加
i.parentElement.classList.add('invalid');
}
});
}
};
HTMLでメールフィールドを定義したと仮定します。
<div>
<label for="email">email</label>
<input type="email" id="email" name="email" required />
<p class="help">Please enter a valid email address</p>
</div>
スクリプトは、メールが指定されていないか無効な場合に<div>
にinvalid
クラスを適用します。CSSは、フォームが送信されたときに検証メッセージを表示または非表示にすることができます:
.help { display: none; }
.invalid .help { display: block; }
.invalid label, .invalid input, .invalid .help {
color: red;
border-color: red;
}
カスタムフォームバリデータの作成
以下のデモンストレーションは、ユーザー名とメールアドレス、電話番号、またはその両方を要求するコンタクトフォームの例を示しています:
これは、FormValidate
という名前の汎用的なフォームバリデーションクラスを使用して実装されています。フォーム要素は、オブジェクトをインスタンス化するときに渡されます。オプションの第二パラメーターを設定できます:
true
は、ユーザーがフィールドと対話するたびに各フィールドを検証するfalse
(デフォルト)は、最初の送信後にすべてのフィールドを検証し、その後のフィールドレベルの検証が発生します
// コンタクトフォームの検証
const contactForm = new FormValidate(document.getElementById('contact'), false);
.addCustom(field, func)
メソッドは、カスタム検証関数を定義します。以下のコードは、email
またはtel
フィールドのいずれかが有効であることを確認します(どちらもrequired
属性を持たない):
// カスタム検証 - メールおよび/または電話
const
email = document.getElementById('email'),
tel = document.getElementById('tel');
contactForm.addCustom(email, f => f.value || tel.value);
contactForm.addCustom(tel, f => f.value || email.value);
A FormValidate
object monitors both of the following:
focusout
イベントは、個々のフィールドをチェックします- フォーム
submit
イベントは、すべてのフィールドをチェックします
両方とも.validateField(field)
メソッドを呼び出し、フィールドが標準の制約検証を通過するかどうかを確認します。通過すると、そのフィールドに割り当てられたカスタム検証関数が順番に実行されます。すべてがtrue
を返す必要があります。
無効なフィールドには、フィールドの親要素にinvalid
クラスが適用され、CSSを使用して赤いヘルプメッセージが表示されます。
最後に、オブジェクトはフォーム全体が有効であるときにカスタムsubmit
関数を呼び出します。
// カスタム submit
contactForm.submit = e => {
e.preventDefault();
alert('Form is valid!\n(open the console)');
const fd = new FormData(e.target);
for (const [name, value] of fd.entries()) {
console.log(name + ': ' + value);
}
}
また、標準のaddEventListener
を使用してフォームsubmit
イベントを処理することもできます。FormValidate
は、フォームが無効な場合に他のハンドラーが実行されないようにします。
フォームフィネス
フォームはすべてのウェブアプリケーションの基盤であり、開発者はユーザ入力を操作するために相当の時間を費やします。制約検証はよくサポートされており、ブラウザはほとんどのチェックを処理し、適切な入力オプションを表示できます。
推奨事項:
- 可能な限り標準のHTML入力タイプを使用してください。
min
、max
、step
、minlength
、maxlength
、pattern
、required
、inputmode
、およびautocomplete
属性を適切に設定してください。 - 必要に応じて、カスタム検証とメッセージを有効にするために少しJavaScriptを使用してください。
- より複雑なフィールドの場合、標準入力を段階的に強化してください。
最後に:インターネットエクスプローラーを忘れてください!
もしあなたのクライアントが主にIEユーザーでない限り、独自のフォールバック検証機能を実装する必要はありません。すべてのHTML5の入力フィールドはIEで動作しますが、より多くのユーザーの努力が必要になる場合があります。(例えば、IEは無効なメールアドレスを入力したときに検出しません。)サーバー側でデータを検証する必要があるため、それをIEのエラーチェックの基盤として考慮してください。
HTMLフォームと制約検証に関するよくある質問(FAQs)
HTMLフォームの検証の重要性は何ですか?
HTMLフォームの検証は、ウェブ開発の重要な側面です。ユーザーがフォームに入力したデータが、サーバーに送信される前に特定の基準を満たしていることを保証します。これはデータの整合性を維持するだけでなく、入力されたデータの正確性に関する即時のフィードバックを提供することで、ユーザーエクスペリエンスを向上させます。フォームの検証がなければ、間違った、不完全な、さらには悪意のあるデータを受け取るリスクがあり、データの破損、セキュリティ侵害、システムクラッシュなど、さまざまな問題が発生する可能性があります。
HTML5はフォームの検証をどのように改善しますか?
HTML5は、フォームの検証をはるかに簡単かつ効率的にするために、いくつかの新しいフォーム要素と属性を導入しています。例えば、email、URL、numberなどの新しい入力タイプを提供し、入力データをタイプに基づいて自動的に検証します。また、required、pattern、min/maxなどの新しい属性を導入し、入力データに対するさまざまな制約を指定できるようにします。さらに、HTML5は、JavaScriptを使用してカスタム検証を実行できる組み込みの検証APIを提供しています。
JavaScriptを使用せずにフォームの検証を行うことはできますか?
はい、HTML5のみを使用して基本的なフォーム検証を実行できます。HTML5は、入力データに対するさまざまな制約を指定できる新しい入力タイプや属性を提供します。たとえば、required属性を使用してフィールドを必須にすることができ、pattern属性を使用して特定のフォーマットを強制することができ、min/max属性を使用して数値入力の範囲を設定することができます。ただし、より複雑な検証の場合は、JavaScriptを使用する必要がある場合があります。
HTML5のフォーム検証でエラーメッセージをカスタマイズするにはどうすればよいですか?
HTML5は、エラーメッセージをカスタマイズできる検証APIを提供します。ValidityStateオブジェクトのsetCustomValidityメソッドを使用して、フィールドのカスタムエラーメッセージを設定できます。このメソッドは文字列引数を取り、フィールドが無効である場合にフィールドの検証メッセージになります。このメソッドを呼び出すことで、無効なイベントに応答して、フィールドの検証に失敗したときにこのメソッドを呼び出すことができます。
HTML5のフォーム検証を無効にするにはどうすればよいですか?
novalidate属性をフォーム要素に追加することで、HTML5のフォーム検証を無効にできます。この属性が存在する場合、ブラウザはフォームが送信される際にフォームに対して検証を実行しません。サーバーサイドで検証を完全に処理したい場合や、カスタムJavaScriptを使用して検証を行いたい場合に役立ちます。
HTML5で複数のフィールドを一緒に検証するにはどうすればよいですか?
HTML5は、複数のフィールドを一緒に検証する組み込みの方法を提供していません。しかし、JavaScriptを使用してこれを実現できます。複数のフィールドの値をチェックし、必要な基準を満たしていない場合にカスタムの有効性メッセージを設定するカスタム検証関数を記述できます。この関数は、フォームの送信イベントやフィールドの入力/変更イベントに応答して呼び出すことができます。
HTML5で別のフィールドの値に基づいてフィールドを検証する方法は?
HTML5は、別のフィールドの値に基づいてフィールドを検証する組み込みの方法を提供していません。しかし、JavaScriptを使用してこれを実現できます。1つのフィールドの値を別のフィールドの値と比較し、一致しない場合にカスタムの有効性メッセージを設定するカスタム検証関数を記述できます。この関数は、フィールドの入力/変更イベントに応答して呼び出すことができます。
HTML5で非同期検証をどのように実行できますか?
HTML5は、非同期検証をボックスからサポートしていません。しかし、JavaScriptを使用してこれを実現できます。AJAXリクエストなどの非同期操作を実行し、結果に基づいてカスタムの有効性メッセージを設定するカスタム検証関数を記述できます。この関数は、フィールドの入力/変更イベントやフォームの送信イベントに応答して呼び出すことができます。
HTML5のフォーム検証でエラーメッセージのスタイルをどのように設定できますか?
エラーメッセージの外観は、HTML5のフォーム検証においてブラウザによって決定され、CSSを直接使用してスタイル付けすることはできません。しかし、JavaScriptを使用してカスタムエラーメッセージを作成し、好みのようにスタイル付けすることは可能です。フィールドが無効であることを判断し、それに応じてカスタムエラーメッセージを表示するために、検証APIを使用できます。
HTMLフォームの検証をどのようにテストできますか?
HTMLフォームの検証をテストするには、フィールドに様々なタイプのデータを入力し、フォームの送信を試みることができます。検証がすべてのケースで正しく機能することを確認するために、有効なデータと無効なデータの両方でテストする必要があります。また、自動化されたテストツールやライブラリを使用して、より包括的なテストを実行することもできます。
Source:
https://www.sitepoint.com/html-forms-constraint-validation-complete-guide/