slop audit
Blog post 55 / Forms and accessibility

HTML autocomplete attribute: setup and testing guide

Use the HTML autocomplete attribute to identify form fields, group addresses, configure password hints, and test autofill behavior before website launch.

By Slop Audit · 8 min read

The HTML autocomplete attribute tells browsers what information a form field expects. Use a specific value such as email, name, or current-password, then test the deployed form with saved browser data. Correct markup helps identify input purpose; it does not guarantee that every browser or password manager will offer the same autofill experience.

For a student project signup or a public contact form, start with the fields you actually collect. This guide covers token selection, address groups, credentials, debugging, and a focused regression test. Use the website form testing checklist for validation, submission, and recovery across the complete task.

HTML autocomplete attribute launch checklist

  1. List each field's meaning, including whose information it collects.
  2. Match supported purposes to standard autocomplete values.
  3. Keep labels, input types, names, and hints consistent.
  4. Separate repeated address groups with ordered tokens.
  5. Test saved-data autofill and manual entry on supported browsers.
  6. Check that application state retains the browser-filled values.
  7. Save markup assertions in CI and review the public form's accessibility.

Choose autocomplete values by field purpose

The HTML Standard's autofill definitions distinguish on, off, and ordered detail tokens. on permits assistance without naming a particular purpose. A detail token such as email tells the browser what kind of value belongs in that field.

Common choices include:

  • name for a full name; given-name and family-name when the interface genuinely needs separate parts.
  • email for an email address and tel for a telephone number.
  • organization for a company or organization name.
  • street-address for a complete street address, or address-line1 and address-line2 for separate lines.
  • address-level2 for a city or locality and postal-code for a postal code.
  • country for a country code, or country-name when the control expects the written name.

Use the vocabulary the platform defines. firstName, zip, and phone-number may be application field names, but they are not replacements for the standard detail tokens. Match country tokens to the values your select actually submits.

The attribute describes meaning independently of the input's application identifier. Keep name and id stable, and avoid splitting names or addresses just to accommodate a guessed autofill layout.

Keep type, label, and autocomplete separate

A working email field needs more than one attribute:

<form action="/contact" method="post">
  <label for="contact-name">Full name</label>
  <input id="contact-name" name="fullName"
    type="text" autocomplete="name" required>

  <label for="contact-email">Email address</label>
  <input id="contact-email" name="email"
    type="email" autocomplete="email" required>

  <button type="submit">Send message</button>
</form>

Here, the label gives the control its visible and accessible name, type="email" supplies email input behavior, autocomplete="email" identifies its purpose, and name="email" supplies its form submission key. Follow the accessible name guide when a field is missing a usable label.

In React JSX, spell the properties autoComplete and htmlFor. Inspect the resulting DOM after hydration: a shared input component may discard a property even when the calling code looks correct.

W3C's Identify Input Purpose explanation covers fields collecting information about the user whose purposes appear in the defined taxonomy. It does not require inventing tokens for every application-specific value. For example, a project title is not a person's name.

The W3C H98 technique checks both a well-formed attribute and agreement between the label's meaning and the token. A valid token on the wrong field still needs correction. Keep a separate review for forms collecting information about someone other than the person filling them in.

Group shipping, billing, and repeated addresses

A form with two addresses needs enough context to distinguish them. The ordered syntax is a section token when needed, a shipping or billing token when applicable, then the field detail token:

<label for="shipping-postcode">Shipping postal code</label>
<input id="shipping-postcode" name="shippingPostalCode"
  autocomplete="shipping postal-code">

<label for="billing-postcode">Billing postal code</label>
<input id="billing-postcode" name="billingPostalCode"
  autocomplete="billing postal-code">

When two shipping addresses must remain separate, use consistent named sections across each address's fields:

<input aria-label="First delivery street address"
  name="firstStreet" autocomplete="section-first shipping street-address">
<input aria-label="First delivery postal code"
  name="firstPostalCode" autocomplete="section-first shipping postal-code">
<input aria-label="Second delivery street address"
  name="secondStreet" autocomplete="section-second shipping street-address">
<input aria-label="Second delivery postal code"
  name="secondPostalCode" autocomplete="section-second shipping postal-code">

This abbreviated example shows grouping; give the production fields visible labels and group headings too. MDN's autocomplete attribute reference documents section grouping and token order. Put section-* first, reuse the section identifier within a group, and keep different groups distinct.

Test the copy-address control separately. A browser hint does not implement “billing address is the same as shipping,” synchronize application state, or decide what the server should receive.

Configure username and password hints

Choose tokens for the current task:

<label for="login-email">Email address</label>
<input id="login-email" name="username" type="email"
  autocomplete="username" required>

<label for="login-password">Password</label>
<input id="login-password" name="password" type="password"
  autocomplete="current-password" required>

An email used as an account identifier can have type="email" and autocomplete="username". Use new-password for a newly chosen password during signup or reset. A separate confirmation field for that new password also uses new-password. Google's sign-in form best practices explains these distinctions and recommends stable identifiers.

For a verification-code input, one-time-code describes the expected value. It does not implement SMS retrieval, verification, expiry, or authentication. Keep those behaviors in the application's tested flow.

Understand autocomplete off before using it

autocomplete="off" requests that the browser avoid filling the control automatically. It is not a reliable way to disable a password manager: MDN notes that browsers may still offer to save and fill login credentials despite this setting.

Review any blanket off on the form before disabling assistance across all fields. Prefer an accurate purpose token where one applies. Do not change field names randomly, inject decoy inputs, or block paste to fight browser behavior. Those changes make the task harder to maintain and test.

A custom search suggestion widget is a separate feature. The HTML attribute does not create a dropdown, fetch suggestions, or establish a combobox's keyboard behavior. If suggestions are part of the task, review their interaction using the keyboard accessibility testing guide.

Debug form autofill on the deployed page

Test in a dedicated browser profile with fictional saved information. A fresh or private profile may have nothing to offer, so a missing suggestion alone does not establish a markup failure.

Use this sequence:

  1. Open the deployed route and inspect the rendered input attributes.
  2. Focus the first relevant field and select a saved profile explicitly.
  3. Check every populated field, including country, postal code, and optional address lines.
  4. Edit one populated value, move focus, and trigger ordinary validation.
  5. Verify that the UI and application state keep the corrected value.
  6. Submit only to an owned test flow; compare the received fields with the displayed values.

Chrome's Autofill panel shows saved address data and the fields it populated, helping trace an address mapped to the wrong input. Use equivalent manual checks in other browsers you support. Follow the mobile website testing routine on a real phone as well.

If a value appears and disappears, inspect rerenders, input remounts, default values, and controlled component state. If the displayed value differs from the submitted payload, inspect the form serializer and state updates before changing tokens. Also test without saved data: manual entry must remain usable.

Add an HTML autocomplete attribute regression check

With Playwright Test installed, adapt this contract to your public contact route and expected labels:

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

test("contact fields preserve their input purposes", async ({ page }) => {
  const response = await page.goto("https://example.com/contact");
  expect(response?.status()).toBe(200);

  const fullName = page.getByRole("textbox", { name: "Full name", exact: true });
  const email = page.getByRole("textbox", { name: "Email address", exact: true });

  await expect(fullName).toBeVisible();
  await expect(fullName).toHaveAttribute("autocomplete", "name");
  await expect(email).toHaveAttribute("type", "email");
  await expect(email).toHaveAttribute("autocomplete", "email");

  await fullName.fill("Alex Example");
  await email.fill("alex@example.com");
  await email.press("Tab");
  await expect(fullName).toHaveValue("Alex Example");
  await expect(email).toHaveValue("alex@example.com");
});

Playwright's web-first assertions retry locator checks while the page settles. This test catches lost attributes, missing labels, and values cleared on the tested blur path. It uses programmatic filling, so it does not exercise a saved browser profile, password manager, or operating-system autofill prompt. Keep the manual browser pass alongside it in your website regression testing checklist.

Check the surrounding form with Slop Audit

After verifying autofill, run Slop Audit on the public form URL. Its bounded Browser Run collects axe accessibility findings, form-label evidence, sampled keyboard focus, and mobile and desktop screenshots when browser capacity is available. Use the report to identify surrounding barriers before you share the form with students, recruiters, or customers.

Slop Audit does not load your saved address profile, exercise password-manager suggestions, submit the form, or verify that autofilled data reached your backend. A clean report cannot certify input-purpose correctness or WCAG conformance. Save the report with your browser, device, build identifier, and manual autofill result so the next release has a concrete comparison.