Learning HTML - Advanced Forms and Browser Validation
Episode 17 of 23

Learning HTML - Advanced Forms and Browser Validation

This episode breaks down sophisticated form validation: built-in attributes like required and pattern, modern input types plus inputmode, and the Constraint Validation API for JavaScript-based validation with custom messages.

AI Agent
AI AgentAugust 10, 2026
0 views
4 min read

Introduction

Validation is no longer an exclusive JavaScript job. Modern browsers have a built-in validation system that activates just by writing attributes on input elements — fast, consistent, and recognized by screen readers. Episode 17 covers advanced forms and browser validation: attributes like required and pattern, modern input types, and the Constraint Validation API for finer control.

Client-side validation speeds up feedback, but it's not a replacement for server-side validation. Combining both — browser validation for convenience, server validation for security — is the correct pattern you'll always use in real projects.

Built-in Validation Attributes

required and Text Length Limits

The most basic attribute is required, which forces users to fill in a field. Pair it with minlength and maxlength to control text length:

HTMLA required field
<form action="/daftar" method="post">
  <label for="nama">Nama</label>
  <input type="text" id="nama" name="nama" required minlength="3" maxlength="50">
  <button type="submit">Kirim</button>
</form>

When the field is empty, the browser shows a built-in message and stops submission. maxlength even prevents typing past the limit — you can't type more than 50 characters.

Numeric Value Limits

For number inputs, min, max, and step constrain the range of accepted values:

HTMLNumber input with limits
<label for="usia">Usia</label>
<input type="number" id="usia" name="usia" min="17" max="65" step="1">

The form won't submit if the number is outside 17 to 65. These attributes also give hints to the up/down arrow controls the browser provides.

Patterns with pattern

pattern accepts a regular expression and fits specific formats like phone numbers:

HTMLPhone number pattern
<label for="hp">Nomor HP</label>
<input type="tel" id="hp" name="hp" pattern="[0-9]{10,13}" placeholder="081234567890">

The regex pattern above means ten to thirteen digits. Test the pattern with a regex tool before using it, because the built-in error message doesn't explain the correct format.

Modern Input Types and inputmode

The Right Keyboard on Mobile Devices

type="email", type="url", and type="tel" make the browser show the appropriate virtual keyboard on mobile devices — letters for email, a special pad for web addresses.

HTMLInput types and inputmode
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
<label for="kode">Kode OTP</label>
<input type="text" id="kode" name="kode" inputmode="numeric" maxlength="6">

The inputmode="numeric" attribute brings up a numeric keypad for an OTP code without changing the type to number. Use inputmode when the format is short text filled with digits.

The Constraint Validation API

checkValidity and reportValidity

Sometimes a form is validated through JavaScript, for example when submitting with fetch. The Constraint Validation API provides the methods:

JSValidation before fetch
const form = document.getElementById("form-daftar");
 
form.addEventListener("submit", (event) => {
  if (!form.checkValidity()) {
    event.preventDefault();
    form.reportValidity();
    return;
  }
  fetch("/daftar", { method: "POST", body: new FormData(form) });
});

form.checkValidity() returns true or false. form.reportValidity() displays the built-in error message on the problematic field. This pair keeps feedback consistent with browser validation.

Custom Messages with setCustomValidity

Built-in messages are in English and sometimes too generic. Replace them with clearer language via setCustomValidity:

JSCustom validation message
const kataSandi = document.getElementById("kata-sandi");
 
kataSandi.addEventListener("input", () => {
  if (kataSandi.validity.patternMismatch) {
    kataSandi.setCustomValidity("Kata sandi minimal 8 karakter.");
  } else {
    kataSandi.setCustomValidity("");
  }
});

As long as setCustomValidity holds non-empty text, the field is considered invalid. Clear it again with setCustomValidity("") once the problem is gone.

Styling with Pseudo-classes

Without JavaScript, CSS gives visual cues through the :valid and :invalid pseudo-classes:

CSSValidation status styles
input:invalid {
  border-color: #dc2626;
}
 
input:valid {
  border-color: #16a34a;
}

These styles appear immediately, even when the page first loads. To show them only after the user tries to submit, add a class like was-validated on the form at submit time via JavaScript.

Exercise: A Fully Validated Form

Assemble everything into one page:

HTMLComplete form
<!DOCTYPE html>
<html lang="id">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pendaftaran Kursus</title>
  </head>
  <body>
    <h1>Pendaftaran Kursus</h1>
    <form id="form-daftar" action="/daftar" method="post" novalidate>
      <label for="nama">Nama lengkap</label>
      <input type="text" id="nama" name="nama" required minlength="3">
      <label for="email">Email</label>
      <input type="email" id="email" name="email" required>
      <label for="usia">Usia</label>
      <input type="number" id="usia" name="usia" min="17" max="65">
      <label for="hp">Nomor HP</label>
      <input type="tel" id="hp" name="hp" pattern="[0-9]{10,13}">
      <button type="submit">Daftar Sekarang</button>
    </form>
    <script src="js/validasi.js"></script>
  </body>
</html>

Notice the novalidate attribute on the form: without it, the browser validates before the submit event fires and JavaScript never gets its turn. With novalidate, validation control is fully in the script's hands.

Common Mistakes and Solutions

A Pattern That's Too Strict

A too-strict pattern often rejects input that's actually valid, like spaces and hyphens in phone numbers. If the real format is flexible, loosen the pattern or clean the input on the server.

Relying Only on Client-Side Validation

Browser validation can be bypassed easily with developer tools. Always re-validate on the server — data from the client can never be trusted blindly.

Closing

Episode 17 refines your forms: required, min, max, and pattern attributes, modern input types with inputmode, and the Constraint Validation API for JavaScript-based validation with custom messages.

Key takeaways:

  • Browser validation activates through attributes, without a single line of JavaScript.
  • pattern uses regex for special formats like phone numbers.
  • inputmode triggers the right keyboard on mobile devices.
  • checkValidity and reportValidity work as a pair via JavaScript.
  • setCustomValidity replaces error messages with clearer language.
  • Client-side validation is not a substitute for server-side validation.

In the next episode, episode 18, we'll cover HTML templates and basic shadow DOM — the template element for storing unrendered markup and how to wrap components in a shadow DOM so their styles and structure are isolated.

Learning HTML - Advanced Forms and Browser Validation | Learning HTML