Autocomplete Attribute and Validation

What does the autocomplete attribute have to do with validation? More than any other attribute: the cheapest validation error is the one that never happens because the browser filled the field correctly. Correct tokens let browsers and password managers fill names, addresses, emails, phone numbers, card details and one-time codes accurately, which removes typos before any rule runs — and WCAG 1.3.5 requires them for fields that collect information about the user. Wrong or missing tokens do the opposite: a card number filled into a phone field, a billing postcode in the delivery address, a password manager saving a one-time code as a password. This recipe chooses tokens for common form fields, scopes them with sections, handles the cases where autofill should be discouraged, and makes sure autofilled values still go through the Constraint Validation API like typed ones.

When Autocomplete Tokens Matter Most

Every field that collects personal information should have a token. They matter most when:

  • Forms are long or repetitive — checkout, registration, applications — where autofill saves the most effort and prevents the most typos.
  • Users are on mobile, where typing an address or card number is slow and error-prone.
  • Users have motor or cognitive disabilities, for whom autofill is an assistive technology; this is why WCAG 1.3.5 Identify Input Purpose is a Level AA requirement.
  • Password managers are involved — sign-in, sign-up, password change and one-time code flows depend on the right tokens to offer, save and generate credentials.

Tokens complement type and inputmode rather than replacing them: type="email" drives validation and the keyboard, autocomplete="email" drives filling. Both belong on the field, as the HTML5 input types and attributes topic describes.

Tokens for common fields A table listing common form fields with the autocomplete token to use and the matching input type or inputmode. autocomplete token type / inputmode Full name name text Email email type=email Phone tel type=tel Postcode postal-code text Card number cc-number inputmode=numeric One-time code one-time-code inputmode=numeric New password new-password type=password
The token tells the browser what to fill; the type and inputmode tell it how to validate and which keyboard to show.

Minimal Working Autocomplete Setup

<form id="checkout" novalidate>
  <fieldset>
    <legend>Contact</legend>
    <label for="name">Full name</label>
    <input id="name" name="name" autocomplete="name" required>
    <label for="email">Email address</label>
    <input id="email" name="email" type="email" autocomplete="email" required>
    <label for="tel">Phone number <span class="optional">(optional)</span></label>
    <input id="tel" name="tel" type="tel" autocomplete="tel">
  </fieldset>

  <fieldset>
    <legend>Delivery address</legend>
    <label for="ship-line1">Address line 1</label>
    <input id="ship-line1" name="shipping.line1" autocomplete="shipping address-line1" required>
    <label for="ship-city">Town or city</label>
    <input id="ship-city" name="shipping.city" autocomplete="shipping address-level2" required>
    <label for="ship-postcode">Postcode</label>
    <input id="ship-postcode" name="shipping.postcode" autocomplete="shipping postal-code" required>
    <label for="ship-country">Country</label>
    <select id="ship-country" name="shipping.country" autocomplete="shipping country" required></select>
  </fieldset>

  <fieldset>
    <legend>Payment</legend>
    <label for="cc-name">Name on card</label>
    <input id="cc-name" name="ccname" autocomplete="cc-name" required>
    <label for="cc-number">Card number</label>
    <input id="cc-number" name="cardnumber" inputmode="numeric" autocomplete="cc-number" required>
    <label for="cc-exp">Expiry date (MM/YY)</label>
    <input id="cc-exp" name="cc-exp" inputmode="numeric" autocomplete="cc-exp" required>
    <label for="cc-csc">Security code</label>
    <input id="cc-csc" name="cvc" inputmode="numeric" autocomplete="cc-csc" required>
  </fieldset>
  <button type="submit">Pay</button>
</form>
// Autofilled values go through exactly the same validation as typed ones.
const form = document.querySelector<HTMLFormElement>("#checkout")!;
let scheduled = false;

function revalidate(): void {
  scheduled = false;
  for (const el of form.querySelectorAll<HTMLInputElement | HTMLSelectElement>("[name]")) {
    runCustomRules(el);                               // Luhn, expiry, postcode by country…
    if (el.getAttribute("aria-invalid") === "true" && el.checkValidity()) {
      el.removeAttribute("aria-invalid");             // withdraw errors the fill fixed
    }
  }
}

// Autofill fires a burst of input/change events; validate once after it settles.
for (const type of ["input", "change"] as const) {
  form.addEventListener(type, () => {
    if (!scheduled) { scheduled = true; requestAnimationFrame(revalidate); }
  });
}

form.addEventListener("submit", (e) => {
  revalidate();
  if (!form.reportValidity()) e.preventDefault();
});

The shipping prefix scopes the address tokens to the delivery block, so a browser holding separate billing and shipping addresses fills each block with the right one. Coalescing the autofill burst into one validation pass prevents rules that depend on several fields — a postcode that depends on the country — from judging a field before its neighbour has been filled, the problem covered in validating autocompleted address fields.

Anatomy of an autocomplete token An autocomplete value is built from an optional section name, an optional billing or shipping hint, an optional contact type, and a required field name. section-* (optional) e.g. section-guest2 shipping / billing address grouping home / work / mobile for contact fields Field name (required) email, postal-code, cc-number Result "shipping postal-code"
Most fields need only the field name; sections and shipping or billing hints keep repeated blocks from being mixed up.

Autocomplete Token Reference

Purpose Token Notes
Full name / parts name, given-name, family-name Prefer one name field where possible
Email email With type="email"
Phone tel (tel-national, tel-country-code) With type="tel"
Address street-address or address-line1..3, address-level1..2, postal-code, country Prefix with shipping / billing
Organisation organization, organization-title
Birthday bday or bday-day, bday-month, bday-year Split fields for dates of birth
Card cc-name, cc-number, cc-exp (or cc-exp-month/cc-exp-year), cc-csc Browsers may require HTTPS
Sign-in username, current-password Lets managers fill saved credentials
Sign-up / change new-password Triggers password generation
One-time code one-time-code SMS code autofill on mobile
Repeated blocks section-<name> prefix e.g. section-guest2 email
Discourage filling off Browsers may ignore it for credentials

Verification Steps

import { test, expect } from "@playwright/test";

test("every personal-data field has a valid autocomplete token", async ({ page }) => {
  await page.goto("/checkout");
  const missing = await page.evaluate(() =>
    [...document.querySelectorAll("input[name], select[name]")]
      .filter((el) => !(el as HTMLInputElement).autocomplete || (el as HTMLInputElement).autocomplete === "on")
      .map((el) => (el as HTMLInputElement).name),
  );
  expect(missing).toEqual([]);
});

Edge Cases and Failure Modes

autocomplete="off" on sign-in fields. Browsers largely ignore it for username and password fields, and trying to block password managers fails WCAG 3.3.8 Accessible Authentication. Use the correct credential tokens instead.

Made-up token values. Values like autocomplete="nope" to defeat autofill are invalid tokens; they fail axe-core’s autocomplete-valid rule and behave inconsistently. Use off where filling genuinely makes no sense (a search-within-results box, a CAPTCHA answer).

Autofill that bypasses your events. Some engines fill fields without dispatching input. Validate on submit regardless, and consider the :autofill animation hook as a backup signal, described in the address guide linked above.

Styling autofilled fields. Browsers paint autofilled inputs with their own background, which can hide your error styling. Keep error indicators that do not rely on background colour — border, icon and text — so an autofilled but invalid value is still visibly wrong.

Designing Fields So Autofill Can Succeed

Tokens only work if the field structure matches what browsers store. Browsers keep one full name, one email, one phone and a small set of address parts per profile; forms that deviate from that shape force autofill to guess, and guesses produce validation errors. A few structural choices make filling reliable. Use one name field rather than first, middle and last unless you truly need the parts. Use street-address in a textarea or address-line1 and address-line2 — not three lines labelled arbitrarily. Put the country selector’s option values as ISO codes and its text as localised names, because browsers match either. Avoid splitting a phone number into several inputs, which most browsers cannot fill. And keep the order of fields conventional for the locale, since some engines use field order as a heuristic when tokens are ambiguous.

Validation rules must accept whatever shape autofill produces. A browser may fill a phone number with an international prefix and spaces, a postcode in lower case, or a name with a trailing space. Normalise before validating — trim, adjust case, strip formatting — so a correct autofilled value never fails a rule that a human typing carefully would pass. The normalisation habits are the same as those in transforming and coercing form input with Zod: accept generously, normalise once, then validate strictly.

Auditing Tokens Across a Product

Autocomplete tokens decay as forms change: a field is renamed, a new block is added by copy-paste, a component library wraps inputs and drops the attribute. A lightweight audit in CI keeps them honest. The Playwright check above fails when a named field has no token; axe-core’s autocomplete-valid rule fails when a token is misspelled or invalid; and a short review list of the product’s forms, with the expected token per field, catches semantic mistakes such as email on a “friend’s email” field that should not be filled with the user’s own address. Run the audit on every form, not just checkout, because sign-up, profile and support forms collect the same personal data.

One-Time Codes and Credential Fields

Credential flows depend on tokens more than any other form. A sign-in form uses username and current-password, so managers fill saved credentials. A sign-up or password-change form uses new-password, so managers offer a generated password and save it afterwards; if the page asks for the current password too, give that field current-password so the manager does not overwrite the wrong one. A verification step uses one-time-code with inputmode="numeric", which lets mobile platforms offer the code from an incoming SMS with one tap — and validation for that field should accept exactly what the platform inserts (digits only, no spaces) rather than enforcing a pattern with separators. These tokens are the difference between a flow that password managers handle perfectly and one that trains users to reuse weak passwords; the password side is covered in password validation patterns.

Credential tokens by form Two columns showing which autocomplete tokens belong on sign-in forms and which on sign-up, password change and verification forms. Sign-in • username (or email) • current-password ✓ managers fill saved credentials ✗ never block paste or autofill Sign-up, change, verify • new-password (+ current-password to confirm) • one-time-code with inputmode=numeric ✓ managers generate and save passwords ✓ platforms fill SMS codes
The right token tells the password manager whether to fill, generate, or read a code from SMS.

Frequently Asked Questions

How does the autocomplete attribute relate to form validation?

Correct tokens let browsers and password managers fill fields accurately, which prevents typos before any validation rule runs. Filled values must still pass the same validation as typed ones.

Is autocomplete required for accessibility?

Yes, for fields collecting information about the user. WCAG 2.2 success criterion 1.3.5 Identify Input Purpose (Level AA) requires programmatically identifiable purpose, which the autocomplete tokens provide.

How do I stop autofill mixing billing and shipping addresses?

Prefix address tokens with shipping or billing, for example autocomplete="shipping postal-code". For other repeated blocks, use a section-name prefix.

Should I use autocomplete="off" on password fields?

No. Browsers mostly ignore it for credentials, and blocking password managers harms security and accessibility. Use current-password on sign-in and new-password on sign-up and password change.

← Back to HTML5 Input Types & Attributes