バリデーション表示とは

必須・形式・文字数などの入力チェックに引っかかった項目に、エラーメッセージを添えて知らせる表示。

概要

フォームの入力内容が条件を満たしていないときに、どの項目が・なぜ問題なのかをエラーメッセージで知らせる表示です。必須項目が空、メールアドレスの形式が違う、文字数が上限を超えているなど、チェックの種類はさまざまです。エラーメッセージは role="alert" を付けて表示し、対象の入力欄には aria-invalid="true" と aria-describedby でメッセージの id を紐付けることで、スクリーンリーダーでも「何が」「なぜ」エラーかが伝わります。

別名

表記ゆれ:入力チェック、エラーメッセージ表示、validation

「入力チェック」はバリデーションの処理そのものを指す言い方で、「バリデーション表示」はそのチェック結果を画面にどう見せるかという、表示側に焦点を当てた呼び方です。

AI への伝え方

「送信ボタンを押したときに、必須・メール形式・100 文字以内の 3 種類をチェックして、エラーがあれば入力欄の下にメッセージを出して」のように、チェックの種類とタイミング(入力のたびに検証するか、送信時にまとめて検証するか)を伝えます。HTML 標準の required や pattern はブラウザ標準の吹き出しで警告を出しますが、見た目をデザインに合わせて自作したい場合は novalidate を付けて JavaScript 側で表示を組み立てる旨も伝えると誤解を防げます。

似たパーツとの違い

「テキスト入力欄」はエラーの有無にかかわらず文字を入力する欄そのもので、バリデーション表示はその欄が条件を満たさなかったときに追加される状態表示という関係です。 「トースト」は画面の隅に一時的に出る通知で、フォーム全体や個別の操作結果を知らせるのに向きますが、バリデーション表示は入力欄 1 つ 1 つに紐付いて表示され続ける点が異なります。

デモ

コード

HTML
<form class="validation-demo" novalidate>
  <div class="validation-demo__field">
    <label class="validation-demo__label" for="validation-demo-name">お名前<span class="validation-demo__required">(必須)</span></label>
    <input
      class="validation-demo__input"
      type="text"
      id="validation-demo-name"
      name="name"
      aria-describedby="validation-demo-name-error"
    />
    <p class="validation-demo__error" id="validation-demo-name-error" role="alert" hidden></p>
  </div>

  <div class="validation-demo__field">
    <label class="validation-demo__label" for="validation-demo-email">メールアドレス</label>
    <input
      class="validation-demo__input"
      type="email"
      id="validation-demo-email"
      name="email"
      aria-describedby="validation-demo-email-error"
    />
    <p class="validation-demo__error" id="validation-demo-email-error" role="alert" hidden></p>
  </div>

  <div class="validation-demo__field">
    <label class="validation-demo__label" for="validation-demo-message"
      >お問い合わせ内容<span class="validation-demo__required">(100文字以内)</span></label
    >
    <textarea
      class="validation-demo__textarea"
      id="validation-demo-message"
      name="message"
      rows="3"
      aria-describedby="validation-demo-message-error"
    ></textarea>
    <p class="validation-demo__error" id="validation-demo-message-error" role="alert" hidden></p>
  </div>

  <button class="validation-demo__submit" type="submit">送信する</button>
</form>
CSS
.validation-demo {
  display: flex;
  flex-direction: column;
  gap: 20px;
  font-family: sans-serif;
  max-width: 320px;
}

.validation-demo__field {
  display: flex;
  flex-direction: column;
}

.validation-demo__label {
  margin-bottom: 6px;
  font-size: 13px;
  font-weight: 700;
  color: #333;
}

.validation-demo__required {
  margin-left: 4px;
  font-weight: 400;
  color: #666;
}

.validation-demo__input,
.validation-demo__textarea {
  padding: 10px 12px;
  border: 1px solid #b3b3b3;
  border-radius: 8px;
  font-size: 14px;
  font-family: inherit;
  color: #333;
  box-sizing: border-box;
}

.validation-demo__input:hover,
.validation-demo__textarea:hover {
  border-color: #666;
}

.validation-demo__input:focus-visible,
.validation-demo__textarea:focus-visible {
  outline: 2px solid #0017c1;
  outline-offset: 2px;
}

.validation-demo__input[aria-invalid="true"],
.validation-demo__textarea[aria-invalid="true"] {
  border-color: #b3261e;
}

.validation-demo__error {
  margin: 6px 0 0;
  font-size: 12px;
  color: #b3261e;
}

.validation-demo__submit {
  align-self: flex-start;
  padding: 10px 24px;
  border: 0;
  border-radius: 8px;
  background: #0017c1;
  color: #fff;
  font-size: 14px;
  cursor: pointer;
}

.validation-demo__submit:hover {
  background: #00118f;
}

.validation-demo__submit:focus-visible {
  outline: 2px solid #0017c1;
  outline-offset: 2px;
}
JS
const validationDemoForm = document.querySelector(".validation-demo");

const validationDemoRules = [
  {
    input: document.getElementById("validation-demo-name"),
    error: document.getElementById("validation-demo-name-error"),
    validate: (value) => (value.trim() ? "" : "お名前を入力してください")
  },
  {
    input: document.getElementById("validation-demo-email"),
    error: document.getElementById("validation-demo-email-error"),
    validate: (value) => {
      if (!value.trim()) return "メールアドレスを入力してください";
      return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) ? "" : "メールアドレスの形式が正しくありません";
    }
  },
  {
    input: document.getElementById("validation-demo-message"),
    error: document.getElementById("validation-demo-message-error"),
    validate: (value) => (value.length > 100 ? "100文字以内で入力してください" : "")
  }
];

validationDemoForm.addEventListener("submit", (event) => {
  event.preventDefault();
  validationDemoRules.forEach(({ input, error, validate }) => {
    const message = validate(input.value);
    if (message) {
      error.textContent = message;
      error.hidden = false;
      input.setAttribute("aria-invalid", "true");
    } else {
      error.hidden = true;
      error.textContent = "";
      input.removeAttribute("aria-invalid");
    }
  });
});