こんにちは!Kredo Blog編集部のさおりです!
フォームに「必須」を付けたのに、スペースだけの入力が通る。短すぎる値をエラーにしたら、書き直しても先へ進めなくなった。入力チェックでは、こうした小さな食い違いが起こります。
原因を探すときは、HTMLが確かめる条件と、アプリで追加した条件を分けると整理しやすくなります。さらに「何を入れたか」だけでなく「手で入力したか、コードで入れたか」も確認しましょう。
この記事では、学習内容と時間を入力する小さな教材を使います。空欄・空白・長さ・数値の範囲を比べ、修正した後にエラーを解除するところまで試せます。2026年10月6日に、Chromeで18ケースを実行して結果を確認しました。
フォームの入力チェックは、HTMLと独自ルールを分ける
入力チェックの役割は、利用者に「どこを直せばよいか」を伝えることです。最初からすべてをJavaScriptで書かず、必須入力や数値の範囲など、HTMLで表せる条件から決めていきます。
今回の教材で入力するのは「学習内容」と「時間」の2項目です。条件を先に日本語で書くと、次のようになります。
- 学習内容は必須。入力欄の長さは3〜12カウント。
- 前後の空白を除いた後も3〜12カウントとし、空白だけは認めない。
- 時間は必須。5〜120分の範囲で、5分刻みにする。
ここでの「カウント」はUTF-16コード単位です。見た目の文字数と常に一致するわけではなく、たとえば😀Aは3カウントになります。教材ではHTMLの長さ制約とJavaScriptの.lengthに合わせています。名前や文章を扱う本番のフォームでは、利用者が理解できる文字数の仕様を別途決めてください。
「空白だけは不可」は、単に必須入力と指定するだけでは表せません。この部分をJavaScriptの独自ルールにします。HTMLとJavaScriptの担当を分ける考え方は、MDNのフォーム検証ガイドでも確認できます。
なお、ブラウザ内のチェックは入力を手助けするものです。実サービスで受け取る値は、サーバー側でも検証します。この教材は送信や保存を行わず、入力の判定だけを比べます。
required・minlength・minとmaxで基本を確かめる

まずはHTMLの属性を見てみましょう。教材の入力欄には、次の制約を付けています。これは入力欄部分の抜粋です。動く一式は後半のZIPに入っています。
<label for="lesson-title">学習内容(必須)</label>
<input id="lesson-title" type="text"
required minlength="3" maxlength="12">
<label for="minutes">時間(分)</label>
<input id="minutes" type="number"
required min="5" max="120" step="5">
requiredは空欄を認めない指定です。minlengthとmaxlengthはテキストの長さ、minとmaxは数値の下限・上限を表します。時間にはstep="5"も指定したので、範囲内でも6分は条件を満たしません。
教材の結果には、入力のどの条件に合わなかったかを示すvalidityを表示します。すべての項目を一度に覚えるより、今試した値と対応させるほうが理解しやすいでしょう。
| 試す値 | 確認する条件 | trueになる主なフラグ |
|---|---|---|
| 学習内容が空欄 | 必須か | valueMissing |
| 学習内容にAIを手入力 | 3カウント以上か | tooShort |
| 時間が0 | 5以上か | rangeUnderflow |
| 時間が125 | 120以下か | rangeOverflow |
| 時間が6 | 5分刻みか | stepMismatch |
スマホでは表を左右に動かせます。学習内容を試すときの時間は30、時間を試すときの学習内容はWebに固定します。
どの制約にも違反しなければvalidはtrueです。独自ルールでメッセージを設定した場合はcustomErrorも判定に加わります。各フラグの意味はMDNのValidityStateを参照できます。
13文字を手で打つと、必ずtooLongが出る、とは考えないでください。今回のChromeではmaxlength="12"の欄に13文字を続けて入力しても、欄に残るのは12文字でした。エラー表示だけでなく、実際に残った値と長さを見ることが大切です。
空白だけの入力は、JavaScriptで扱いを決める

何も入力していない値は空文字列''です。一方、半角スペースを3個入れた値には、空白という文字が3個あります。今回のテキスト欄では、後者は必須と最低3カウントの条件を満たします。
そこで、前後の空白を除いた文字列を作り、その長さを確かめます。trim()は元の文字列を変更せず、新しい文字列を返します。今回の処理でも、入力欄の値そのものは書き換えず、判定に使う値だけを作る方針です。動作はMDNのtrim()で確認できます。
function titleError(value) {
if (value === '') return ''; // 空欄はHTMLのrequiredで扱う
const cleaned = value.trim();
if (cleaned.length === 0) return '空白だけではなく、学習内容を入力してください。';
if (cleaned.length < 3) return '前後の空白を除いて3カウント以上にしてください。';
if (cleaned.length > 12) return '前後の空白を除いて12カウント以内にしてください。';
return '';
}
この関数は、条件に合わなければエラーメッセージ、合えば空文字列を返します。最初の空欄チェックで空文字列を返しているのは、空欄を許可するためではありません。空欄のエラーはHTMLのrequiredに任せるためです。
たとえば「 A 」は、入力全体では3カウントでも、前後の空白を除くと1カウントです。HTMLだけの判定は通り、独自ルールでは止まります。「 Web 」なら入力全体は7、空白を除くと3なので、両方の条件を満たします。
この教材は入力全体のHTML制約と、空白を除いた独自制約の両方を使います。trim後が12以下なら、入力時のmaxlengthを無視できるという意味ではありません。空白を許す位置や数、保存前に整形するかどうかは、作るフォームの目的に合わせて決めましょう。
直した後もエラーが残るときは解除を確かめる
独自メッセージはsetCustomValidity()で設定できます。ここでつまずきやすいのは、値を書き直しても、前に設定したメッセージが自動で消えるとは限らないことです。
setCustomValidity('')のように空文字列を渡して解除します。教材では入力が変わったら古い独自エラーを消し、確認ボタンを押したときに新しい値で判定し直しています。基本となる部分は次のとおりです。先ほどのtitleError()と一緒に使います。
const titleInput = document.querySelector('#lesson-title');
titleInput.addEventListener('input', () => {
titleInput.setCustomValidity('');
});
function checkTitle() {
titleInput.setCustomValidity(titleError(titleInput.value));
return titleInput.checkValidity();
}
空文字列を渡して消えるのは独自エラーです。入力が空欄ならrequired、時間が範囲外なら数値の制約は引き続き働きます。「エラー解除」と「すべての条件を満たした」は同じ意味ではありません。
関数とメッセージの関係はMDNのsetCustomValidity()に記載されています。教材の画面では、修正後に古い結果も消し、「入力変更後は未確認」に戻します。前の合格表示が残って、新しい値も確認済みに見えてしまうのを避けるためです。
checkValidity()は条件を満たすかを返します。reportValidity()は検証に加えてブラウザのメッセージ表示も行います。教材の「ブラウザのメッセージを見る」で違いを試せます。日本語の文言や表示方法は、ブラウザと言語設定によって変わります。
手入力とコードで入れた値を、ローカル教材で比べる

もう一つ、結果の見落としにつながる違いがあります。HTML標準のminlengthとmaxlengthの検証は、ユーザーが入力した値を対象とします。JavaScriptでvalueへ代入した値では、長さの制約が同じようには検証されません。詳しくはMDNの制約検証ガイドで確認できます。
教材には「コードで2文字を入れる」という比較用ボタンを用意しました。まず自分でAIと入力して確認し、その後でボタンを押してみてください。文字列が同じでも、HTMLだけの判定が変わります。
titleInput.value = 'AI';
titleInput.setCustomValidity('');
console.log(titleInput.checkValidity());
// この教材のHTML標準の長さ判定では true
titleInput.setCustomValidity(titleError(titleInput.value));
console.log(titleInput.checkValidity());
// 独自ルールを加えると false
この例は教材と同じrequired minlength="3" maxlength="12"の欄を使う場合の結果です。文字列を直接調べる独自ルールは、どちらの経路でも2カウントを検出します。「入力欄に値が見えている」だけで、同じ試験をしたことにはならないわけです。
教材を起動する
ZIPを展開し、そのフォルダーをターミナルで開いて、次のコマンドを実行します。Node.jsが使える環境が必要ですが、追加パッケージのインストールは不要です。準備が必要な場合はJavaScriptの開発環境の作り方も参考にしてください。
node server.mjs 8773
ブラウザでhttp://127.0.0.1:8773/を開きます。終了するときはターミナルでCtrl+Cを押してください。同じポートが使われていたら、8774など別の番号で起動し、URLの番号も合わせます。
最初に学習内容をWeb、時間を30にして「2つの判定を比べる」を押します。次は一方の値だけを変えて、結果のacceptedとvalidityを読みましょう。画面にはtrueになった問題フラグと全体のvalidを出し、falseの問題フラグは省略しています。
教材のフォームには、比較のためnovalidateを付けています。送信時の自動検証を止め、ボタンから明示的にcheckValidity()を呼ぶ設計です。送信処理は止めてあり、入力は外部へ送信・保存されません。novalidateを付けるだけで検証が完成する、という例ではありません。
確認した結果の一部
| 学習内容と入力方法 | HTMLだけ | 独自ルール追加後 |
|---|---|---|
| 空欄 | 不適合:必須 | 不適合:必須 |
| 半角スペース3個を手入力 | 条件を満たす | 不適合:空白だけ |
| AIを手入力 | 不適合:短すぎる | 不適合:独自の長さ条件も追加 |
| AIをコードで代入 | 条件を満たす | 不適合:短すぎる |
| Webを手入力 | 条件を満たす | 条件を満たす |
| 13文字をコードで代入 | 条件を満たす | 不適合:長すぎる |
スマホでは表を左右に動かせます。時間はすべて30です。教材と同じ制約で2026年10月6日にChromeで確認した結果です。
ZIPのcases.jsonに18ケースの期待値、check-memo.csvに自分の予想と実測を記入する欄を入れています。半角・全角スペース、前後の空白、上下限、5分刻み、絵文字を含む長さも試せます。
練習:境目と修正後の動きを確認する
一度動いたら、次は「どこで結果が変わるか」を説明してみましょう。答えを見る前に、予想をメモしてから入力してください。
- 時間を30に固定し、学習内容を空欄・半角スペース3個・Webの順に変える。どのフラグが変わるでしょうか。
- 前後に1個ずつ空白を付けた
Aと、2個ずつ付けたWebを比べる。入力全体とtrim後の長さはいくつでしょうか。 AIを手入力した結果と、「コードで2文字を入れる」の結果を比べる。HTMLだけの判定が違う理由を説明してください。- 学習内容をWeb、時間を6にして確認し、5へ直して再確認する。最後にリセットし、古い結果や文字数が残らないか確認してください。
解答の考え方
1問目は、空欄ならvalueMissing、スペース3個なら独自ルールのcustomErrorが手がかりです。Webならどちらも条件を満たします。2問目は3→1カウントと7→3カウントの違いです。見た目が似た入力でも、どの値を数えているかを区別します。
3問目は長さ制約の対象となる入力経路の違いです。4問目はstepMismatchが消えることに加え、修正直後は未確認、再確認後は合格、リセット後は空欄・時間30・長さ0・未確認へ戻ることを見ます。エラーが出るかだけでなく、利用者が直して先に進めるかまで試すのがポイントです。
テスト項目の広げ方はAIで作ったアプリのテスト方法で整理しています。入力チェックを理解した後で、値の保存まで実装したい場合はJavaScriptで学習記録アプリを作る教材へ進めます。
フォームの入力チェックでよくある質問
minlengthだけ付ければ、必須入力になりますか?
なりません。空欄も禁止したい場合はrequiredを別に指定します。最低文字数の指定と、入力そのものが必須かどうかは別の条件です。長さがUTF-16コード単位で扱われる点も、MDNのminlengthで確認できます。
空白を全部消してから判定すればよいですか?
何を入力する欄かによります。今回のtrim()は前後の空白を除くだけで、途中の空白は残します。文章、氏名、識別用のコードでは必要な扱いが異なります。先に条件を決め、入力値を勝手に変えると困らないかも考えましょう。
メールアドレスもこの教材で検証できますか?
この教材はテキストの学習内容と数値の時間を対象にしています。メール欄の短い例はJavaScriptサンプルコード集にあります。形式を確かめることと、そのアドレスで実際に受信できることは別の確認です。
入力チェックに通れば、そのまま送信して大丈夫ですか?
ブラウザ側の合格だけで、サーバー側の検証を省略することはできません。また、送信後にはHTTP状態や応答本文の確認も必要です。通信を実装する段階ではfetchエラーの調べ方を参考に、入力の問題と通信の問題を分けて確認してください。
まずは教材で、一つの値を変えたときにどの判定が変わるかを追ってみましょう。条件を言葉で決め、入力し、結果を読み、直した後も試す。この順番が分かると、フォームの小さな不具合を自分で切り分けやすくなります。
英語でIT・AIを学べるKredo
英語×IT・AIのスキルを身につけてグローバルに活躍しませんか?
当メディアを運営しているKredoは、英語×ITをオンラインで学ぶ「Kredoオンラインキャンプ」と、フィリピンのセブ島で英語とIT・AIを学ぶ「KredoIT留学」「KredoAI留学」を提供しています。これまでの卒業生は3,000名以上。卒業生の多くが、国内外のIT企業への転職、フリーランスなどへのキャリアチェンジを実現しています。これからの時代に必要な英語×IT・AIのスキルを身につけてグローバルに活躍しませんか?









