テキストボックス 2 — 書式バリデーション

フォーム 初級

このコンポーネントについて

フォームに郵便番号・電話番号・メールアドレスを入力させるとき、書式が誤ったままデータが送信されると後処理が複雑になります。 入力時点で使えない文字をキーボードレベルで弾き、さらにチェックボタンで書式を即座に確認させる構成は、ユーザーのミスを早期に防ぎ入力体験を改善します。

会員登録・配送先入力・お問い合わせフォームなど、正確な情報入力が求められる場面で活用できます。 このページでは3種類のフィールドに「入力フィルタリング」と「書式チェック(OK/NG表示)」を組み合わせたパターンを動くデモで確認でき、そのままコピペして使えます。

  • 郵便番号(3桁-4桁 自動ハイフン) — 数字のみ受け付け、3文字入力後にハイフンを自動挿入。チェックで 000-0000 形式を検証
  • 電話番号(数字・ハイフンのみ) — 数字とハイフン以外のキー入力を無効化。チェックで市外局番パターン(固定・携帯)を検証
  • メールアドレス(使用可能文字限定) — メールアドレスに使えない文字を入力時点でブロック。チェックで正規表現によるフォーマット検証を実施

デモ

Pattern 1 — 郵便番号(自動ハイフン+書式チェック)

※ 数字のみ入力可。3桁入力後にハイフンを自動挿入します

Pattern 2 — 電話番号(入力フィルタリング+書式チェック)

※ 数字とハイフン(-)のみ入力可

Pattern 3 — メールアドレス(入力フィルタリング+書式チェック)

※ メールアドレスに使用できない文字は入力できません

サンプルソース

3つのファイルを同じフォルダに保存し、index.html をブラウザで開くとすぐに動作確認できます。
ファイル名:index.html / style.css / script.js — 保存時の文字コードは UTF-8 を指定してください(Shift-JISだと日本語が文字化けします)。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>書式バリデーション サンプル</title>
  <link rel="stylesheet" href="./style.css">
</head>
<body>

<!-- Pattern 1: 郵便番号(自動ハイフン+書式チェック) -->
<div class="tb2-pattern">
  <label class="tb2-field-label" for="postal-input">郵便番号</label>
  <div class="tb2-input-row">
    <input type="text" id="postal-input" class="tb2-input"
           inputmode="numeric" maxlength="8" placeholder="例:123-4567">
    <button type="button" class="tb2-check-btn" onclick="checkPostal()">チェック</button>
  </div>
  <p class="tb2-status" id="postal-status" aria-live="polite"></p>
  <span class="tb2-hint">※ 数字のみ入力可。3桁入力後にハイフンを自動挿入します</span>
</div>

<!-- Pattern 2: 電話番号(入力フィルタリング+書式チェック) -->
<div class="tb2-pattern">
  <label class="tb2-field-label" for="phone-input">電話番号</label>
  <div class="tb2-input-row">
    <input type="text" id="phone-input" class="tb2-input"
           inputmode="tel" maxlength="13" placeholder="例:03-1234-5678">
    <button type="button" class="tb2-check-btn" onclick="checkPhone()">チェック</button>
  </div>
  <p class="tb2-status" id="phone-status" aria-live="polite"></p>
  <span class="tb2-hint">※ 数字とハイフン(-)のみ入力可</span>
</div>

<!-- Pattern 3: メールアドレス(入力フィルタリング+書式チェック) -->
<div class="tb2-pattern">
  <label class="tb2-field-label" for="email-input">メールアドレス</label>
  <div class="tb2-input-row">
    <input type="text" id="email-input" class="tb2-input"
           inputmode="email" placeholder="例:[email protected]">
    <button type="button" class="tb2-check-btn" onclick="checkEmail()">チェック</button>
  </div>
  <p class="tb2-status" id="email-status" aria-live="polite"></p>
  <span class="tb2-hint">※ メールアドレスに使用できない文字は入力できません</span>
</div>

<script src="./script.js"></script>
</body>
</html>
/* === 書式バリデーション サンプル ===
   色を変えたいときは :root の変数を書き換えるだけでOKです */
:root {
  --color-accent:  #2B7FE8; /* フォーカス・チェックボタンの色 */
  --color-ok:      #15803D; /* OKメッセージのテキスト色 */
  --color-ok-bg:   #DCFCE7; /* OKメッセージの背景色 */
  --color-ng:      #B91C1C; /* NGメッセージのテキスト色 */
  --color-ng-bg:   #FEE2E2; /* NGメッセージの背景色 */
  --color-text:    #1A2332; /* 入力テキスト色 */
  --color-label:   #5A6A7A; /* ラベル文字色 */
  --color-border:  #D0D7E0; /* 通常時のボーダー色 */
  --color-bg:      #F4F6F9; /* カード背景色 */
  --color-hint:    #9AA5B4; /* ヒントテキスト色 */
}

/* 各パターンを囲むカード */
.tb2-pattern {
  margin-bottom: 16px;
  padding: 20px;
  background: var(--color-bg);
  border-radius: 8px;
  max-width: 520px;
}
.tb2-pattern:last-child { margin-bottom: 0; }

/* フィールドラベル */
.tb2-field-label {
  display: block;
  margin-bottom: 5px;
  font-size: 12px;
  font-weight: 500;
  color: var(--color-label);
}

/* inputとチェックボタンを横並びにする */
.tb2-input-row {
  display: flex;
  gap: 8px;
  align-items: center;
}

/* テキスト入力欄 */
.tb2-input {
  flex: 1;
  padding: 9px 12px;
  border: 1.5px solid var(--color-border);
  border-radius: 6px;
  font-size: 14px;
  color: var(--color-text);
  background: #fff;
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s;
  box-sizing: border-box;
  font-family: sans-serif;
}
.tb2-input:focus {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(43, 127, 232, 0.12);
}

/* チェックボタン */
.tb2-check-btn {
  flex-shrink: 0;
  padding: 9px 16px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: var(--color-accent);
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-family: sans-serif;
  transition: background 0.15s;
  white-space: nowrap;
}
.tb2-check-btn:hover { background: #1A6FD4; }

/* OK/NGステータス表示 */
.tb2-status {
  display: none;
  margin: 8px 0 0;
  padding: 6px 10px;
  font-size: 13px;
  font-weight: 600;
  border-radius: 5px;
}
.tb2-status.ok {
  display: block;
  color: var(--color-ok);
  background: var(--color-ok-bg);
}
.tb2-status.ng {
  display: block;
  color: var(--color-ng);
  background: var(--color-ng-bg);
}

/* ヒントテキスト */
.tb2-hint {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  color: var(--color-hint);
}

/* スマホ対応: 600px以下でカードを全幅に */
@media (max-width: 600px) {
  .tb2-pattern { max-width: 100%; }
  .tb2-check-btn { padding: 9px 12px; }
}
// --- 書式検証の正規表現 ---
var POSTAL_REGEX = /^\d{3}-\d{4}$/;
var PHONE_REGEX  = /^\d{2,4}-\d{2,4}-\d{4}$/;
var EMAIL_REGEX  = /^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/;

// --- ステータス表示の共通処理 ---
function showStatus(el, isOk, okMsg, ngMsg) {
  el.className = 'tb2-status ' + (isOk ? 'ok' : 'ng');
  el.textContent = isOk ? okMsg : ngMsg;
}
function hideStatus(el) {
  el.className = 'tb2-status';
  el.textContent = '';
}


// === Pattern 1: 郵便番号 ===
var postalInput  = document.getElementById('postal-input');
var postalStatus = document.getElementById('postal-status');

// 数字のみ許可(特殊キーは通過させる)
postalInput.addEventListener('keydown', function (e) {
  var allowedKeys = ['Backspace', 'Delete', 'Tab', 'ArrowLeft', 'ArrowRight', 'Home', 'End'];
  if (allowedKeys.indexOf(e.key) !== -1) return;
  if (e.ctrlKey || e.metaKey) return;
  if (!/^\d$/.test(e.key)) {
    e.preventDefault();
  }
});

// 入力後: 数字を抽出して「NNN-NNNN」に整形する
postalInput.addEventListener('input', function () {
  hideStatus(postalStatus);
  var digits = postalInput.value.replace(/\D/g, '').slice(0, 7);
  if (digits.length >= 4) {
    postalInput.value = digits.slice(0, 3) + '-' + digits.slice(3);
  } else {
    postalInput.value = digits;
  }
});

function checkPostal() {
  var ok = POSTAL_REGEX.test(postalInput.value);
  showStatus(
    postalStatus, ok,
    '✓ 正しい郵便番号形式です',
    '✗ 「000-0000」の形式で入力してください'
  );
}


// === Pattern 2: 電話番号 ===
var phoneInput  = document.getElementById('phone-input');
var phoneStatus = document.getElementById('phone-status');

// 数字とハイフンのみ許可
phoneInput.addEventListener('keydown', function (e) {
  var allowedKeys = ['Backspace', 'Delete', 'Tab', 'ArrowLeft', 'ArrowRight', 'Home', 'End'];
  if (allowedKeys.indexOf(e.key) !== -1) return;
  if (e.ctrlKey || e.metaKey) return;
  if (!/^[\d\-]$/.test(e.key)) {
    e.preventDefault();
  }
});

// 貼り付け後に数字・ハイフン以外を除去するサニタイズ
phoneInput.addEventListener('input', function () {
  hideStatus(phoneStatus);
  var sanitized = phoneInput.value.replace(/[^\d\-]/g, '');
  if (sanitized !== phoneInput.value) {
    phoneInput.value = sanitized;
  }
});

function checkPhone() {
  var ok = PHONE_REGEX.test(phoneInput.value);
  showStatus(
    phoneStatus, ok,
    '✓ 正しい電話番号形式です',
    '✗ 「XX-XXXX-XXXX」の形式で入力してください'
  );
}


// === Pattern 3: メールアドレス ===
var emailInput  = document.getElementById('email-input');
var emailStatus = document.getElementById('email-status');

// メールアドレスに使えない文字を弾く
emailInput.addEventListener('keydown', function (e) {
  var allowedKeys = ['Backspace', 'Delete', 'Tab', 'ArrowLeft', 'ArrowRight', 'Home', 'End'];
  if (allowedKeys.indexOf(e.key) !== -1) return;
  if (e.ctrlKey || e.metaKey) return;
  // 1文字キーのうち使用不可文字だけブロック
  if (e.key.length === 1 && /[^\w.@+\-]/.test(e.key)) {
    e.preventDefault();
  }
});

// 貼り付け後に使用不可文字を除去するサニタイズ
emailInput.addEventListener('input', function () {
  hideStatus(emailStatus);
  var sanitized = emailInput.value.replace(/[^\w.@+\-]/g, '');
  if (sanitized !== emailInput.value) {
    emailInput.value = sanitized;
  }
});

function checkEmail() {
  var ok = EMAIL_REGEX.test(emailInput.value);
  showStatus(
    emailStatus, ok,
    '✓ 正しいメールアドレス形式です',
    '✗ 正しいメールアドレスの形式で入力してください'
  );
}

AI用プロンプト

各パターンのプロンプトをコピーしてAIに渡すと、同様のコンポーネントを生成できます。

※ このプロンプトを使ってもデモとまったく同じ動作にならない場合があります。AIの解釈や生成タイミングによって差が出ることをご了承ください。

💡 jQuery・Vue・React など特定のライブラリで実装したい場合は、プロンプトの末尾に「〇〇を使って実装してください」と追記してください。

Pattern 1 — 郵便番号(自動ハイフン+書式チェック)

# テキストボックス(郵便番号・自動ハイフン+書式チェック)作成依頼

## 概要
郵便番号入力フィールドを実装してください。数字のみ入力を受け付け、3桁入力後にハイフンを自動挿入し、チェックボタンで書式(000-0000)を検証してOK/NGを表示します。

## 要件
- 数字(0〜9)以外のキー入力を無効化する(Backspace・Delete・矢印キー等は許可)
- 3文字の数字を入力した直後に「-」を自動挿入してカーソルを4文字目に移動する
- maxlength="8"(「000-0000」の8文字)
- 「チェック」ボタンを押すと /^\d{3}-\d{4}$/ で検証する
  - OK: 緑色で「✓ 正しい郵便番号形式です」を表示
  - NG: 赤色で「✗ 「000-0000」の形式で入力してください」を表示
- フィールドの値を変更するとステータス表示を非表示にリセットする

## 技術仕様
- HTML / CSS / バニラJavaScript で実装
- 外部ライブラリ:なし
- レスポンシブ対応:必要

## 動作詳細
keydown イベントで数字・特殊キー以外を preventDefault する。
input イベントで value から数字のみ抽出し、4文字以上なら「NNN-NNNN」形式に再フォーマットして input.value に書き戻す。

## 出力形式
HTML・CSS・JavaScriptを分けて出力してください。
各ファイルは単独でコピー&ペーストして使えるよう記述してください。

Pattern 2 — 電話番号(入力フィルタリング+書式チェック)

# テキストボックス(電話番号・入力フィルタリング+書式チェック)作成依頼

## 概要
電話番号入力フィールドを実装してください。数字とハイフンのみ受け付け、チェックボタンで一般的な電話番号形式(XX-XXXX-XXXX)を検証してOK/NGを表示します。

## 要件
- 数字(0〜9)とハイフン(-)以外のキー入力を無効化する(Backspace・Delete・矢印キー等は許可)
- maxlength="13"(「0000-0000-0000」の最大13文字)
- 「チェック」ボタンを押すと /^\d{2,4}-\d{2,4}-\d{4}$/ で検証する
  - OK: 緑色で「✓ 正しい電話番号形式です」を表示
  - NG: 赤色で「✗ 「XX-XXXX-XXXX」形式で入力してください」を表示
- フィールドの値を変更するとステータス表示を非表示にリセットする

## 技術仕様
- HTML / CSS / バニラJavaScript で実装
- 外部ライブラリ:なし
- レスポンシブ対応:必要

## 動作詳細
keydown イベントで数字・ハイフン・特殊キー(Backspace, Delete, Tab, Arrow系)以外を preventDefault する。
貼り付け対策として input イベントでも数字・ハイフン以外の文字を除去するサニタイズを行う。

## 出力形式
HTML・CSS・JavaScriptを分けて出力してください。
各ファイルは単独でコピー&ペーストして使えるよう記述してください。

Pattern 3 — メールアドレス(入力フィルタリング+書式チェック)

# テキストボックス(メールアドレス・入力フィルタリング+書式チェック)作成依頼

## 概要
メールアドレス入力フィールドを実装してください。使用不可文字のキー入力を弾き、チェックボタンでメールアドレスの書式を検証してOK/NGを表示します。

## 要件
- スペース・全角文字など、メールアドレスに使用できない文字のキー入力を無効化する
  - 許可する文字: 半角英数字、および . _ % + - @ の記号
- 「チェック」ボタンを押すと正規表現でメールアドレス形式を検証する
  - 正規表現例: /^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/
  - OK: 緑色で「✓ 正しいメールアドレス形式です」を表示
  - NG: 赤色で「✗ 正しいメールアドレスの形式で入力してください」を表示
- フィールドの値を変更するとステータス表示を非表示にリセットする

## 技術仕様
- HTML / CSS / バニラJavaScript で実装
- 外部ライブラリ:なし
- レスポンシブ対応:必要

## 動作詳細
keydown イベントで e.key.length === 1 のとき /[^\w.@+\-]/.test(e.key) が true なら preventDefault する。
貼り付け対策として input イベントでも使用不可文字を正規表現で除去するサニタイズを行う。

## 出力形式
HTML・CSS・JavaScriptを分けて出力してください。
各ファイルは単独でコピー&ペーストして使えるよう記述してください。

同じカテゴリーの事例

現在準備中です。