A checkout page collects a shipping address and a billing address, each with its own street and postal-code inputs. How do you write the autocomplete attributes so the browser fills the two groups separately?
answer
- two addresses look identical to the browser
- tokens before the field name
- two modes only, and they are fixed
- invent your own group name
- order is fixed, not free
basics
~20 sPrefix the field name with a grouping token: autocomplete="shipping street-address" on one group and autocomplete="billing street-address" on the other. For two groups of the same kind, add a section-* prefix such as section-gift shipping street-address.
solid answer
~50 sThe autofill vocabulary is not just field names — a value may carry grouping tokens before the field name, in a fixed order: an optional `section-*` prefix, then `shipping` or `billing`, then for contact fields `home` / `work` / `mobile`, then the field name itself. So the shipping block reads `shipping street-address`, `shipping address-level2`, `shipping postal-code`, and the billing block reads `billing street-address`, `billing address-level2`, `billing postal-code`. Without the prefixes both blocks look identical to the browser, which is why the classic bug is one saved address landing in both. If you need two groups of the *same* mode — say two shipping addresses on a gift order — use an arbitrary `section-*` name to distinguish them: `section-gift shipping street-address` versus `section-home shipping street-address`. The order is fixed; `shipping section-gift street-address` is not a valid value. Suppressing autofill with `off` on the second block is the wrong fix — it removes help rather than describing the field.
code
html · 13 lines<fieldset>
<legend>Deliver to</legend>
<input name="ship_street" autocomplete="shipping street-address">
<input name="ship_city" autocomplete="shipping address-level2">
<input name="ship_zip" autocomplete="shipping postal-code">
</fieldset>
<fieldset>
<legend>Billing address</legend>
<input name="bill_street" autocomplete="billing street-address">
<input name="bill_city" autocomplete="billing address-level2">
<input name="bill_zip" autocomplete="billing postal-code">
</fieldset>go deeper
Know that autocomplete values can carry a shipping or billing prefix before the field name, and that a checkout with two addresses needs them on every field of both blocks.
State the full token order — section-*, then shipping or billing, then a contact qualifier, then the field name — and explain that an out-of-order value is unrecognised and silently falls back to guessing.
Diagnose the duplicate-address symptom from a live checkout, and know that section-* is the escape hatch when two groups share a mode. Keep the token grouping separate from the name attributes the server consumes.
Treat checkout autofill as a conversion surface: decide where the address component owns its tokens, how multi-address flows are named consistently, and how it is verified so a redesign does not quietly regress the fill.
## The problem this solves A browser's autofill store holds structured profiles: an address, maybe several, plus payment methods. When a form contains one postal-code field, matching it to the profile is easy. When it contains two — shipping and billing — the browser has to decide whether they are the same address entered twice or two distinct ones. Nothing in `<input name="zip2">` answers that question, so the browser guesses, and the familiar symptom is a user's home address dropped into both blocks, or the second block left empty. ## The grammar An autocomplete value is a token sequence, not a single word. The permitted order is: ``` [section-*] [shipping | billing] [home | work | mobile | fax | pager] field-name ``` Everything except the field name is optional, and the order is fixed — a value whose tokens appear in a different order is not a recognised autofill value at all, and you silently fall back to heuristics. - **`shipping` / `billing`** are the *autofill modes*. They apply to address and contact fields and say which address this field belongs to. - **`home` / `work` / `mobile` / `fax` / `pager`** narrow contact details: `shipping mobile tel` is the mobile number for the delivery contact. - **`section-*`** is an arbitrary group name you invent. Anything after the `section-` prefix is yours: `section-gift`, `section-passenger-1`. Fields sharing a section name form one logical group. ## The worked checkout ```html <fieldset> <legend>Shipping address</legend> <input autocomplete="shipping name"> <input autocomplete="shipping street-address"> <input autocomplete="shipping address-level2"> <input autocomplete="shipping postal-code"> <input autocomplete="shipping country"> </fieldset> <fieldset> <legend>Billing address</legend> <input autocomplete="billing name"> <input autocomplete="billing street-address"> <input autocomplete="billing address-level2"> <input autocomplete="billing postal-code"> <input autocomplete="billing country"> </fieldset> ``` With this markup the browser can offer the delivery address in one block and the card's registered address in the other, and filling one does not disturb the other. ## When one mode is not enough Modes come in exactly two flavours, so a form with two addresses of the same kind — a gift order with a recipient and a sender, a booking with several travellers, a form that captures a previous address for a credit check — needs `section-*`: ```html <input autocomplete="section-recipient shipping street-address"> <input autocomplete="section-recipient shipping postal-code"> <input autocomplete="section-sender shipping street-address"> <input autocomplete="section-sender shipping postal-code"> ``` The names carry no meaning to the browser; what matters is that fields in the same section belong together and fields in different sections do not. Keep them stable, since changing them changes the grouping. ## Payment fields The card fields — `cc-name`, `cc-number`, `cc-exp`, `cc-csc` — are their own group and do not take `shipping` or `billing`. They can still take a `section-*` prefix if a page genuinely collects more than one card, which is rare. Note also that the security code is a value browsers deliberately avoid storing, so expect the user to type `cc-csc` even when everything else fills. ## Mistakes that show up in review **Token order reversed.** `shipping section-gift street-address` is not valid. `section-*` comes first. **A mode on a field that has no mode.** `billing username` is not meaningful; modes belong on address and contact fields. **Making up a mode.** `delivery`, `home-address`, `primary` are not autofill modes. The two mode tokens are `shipping` and `billing`; anything else has to be expressed with `section-*`. **Reaching for `off` on the second block.** It suppresses help instead of describing the field, and browsers may ignore it anyway. Describe, do not suppress. **Relying on a "same as shipping" checkbox alone.** The checkbox is good UX and worth having, but it is your script copying values; it does nothing for the case where the two addresses genuinely differ, which is the case that needed the grouping tokens in the first place. **Duplicating `name` values.** Grouping tokens describe the fields to the browser; your server still needs distinct `name` attributes (`shipping_zip`, `billing_zip`) to receive both values. The two mechanisms are independent. ## Why this is worth the effort A long checkout is where conversion is lost, and the address blocks are the longest part. A form the browser can fill in two taps rather than forty keystrokes on a phone converts measurably better, and it produces cleaner data — a browser-supplied address is a structured record from the user's profile, not a hand-typed string with a transposed postcode. The grouping tokens are the difference between autofill helping once and autofill helping for the whole form.
- A gift-order form has both a recipient address and a sender address, and both are shipping. How do you distinguish them?With `section-*`. Give each group an invented name and put it first: `section-recipient shipping street-address` against `section-sender shipping street-address`, repeated across every field of each block. The browser treats fields sharing a section name as one logical address group. The names mean nothing to the browser, so pick something stable and readable — changing them changes the grouping.
- Does the shipping or billing token change what the server receives on submit?No. Autocomplete tokens describe fields to the browser and never touch submission. The server sees the `name` attribute and the value, so you still need distinct names like `shipping_postcode` and `billing_postcode`. Confusing the two mechanisms leads to forms where both blocks submit under one name and one address silently wins.
- The team's fix for the duplicate-address bug is a "billing same as shipping" checkbox. Is that enough?It is a good addition but not a substitute. The checkbox is your own script copying values, and it only helps in the case where the addresses match. The bug you were fixing — the browser filling both blocks with the same stored address when they genuinely differ — is untouched by it. Keep the checkbox for convenience and add the grouping tokens for correctness.
saying these in an interview costs you the question
- Writes the section prefix after the shipping token
- Invents modes such as delivery or primary
- Turns autofill off on the second address block
- Thinks grouping tokens change what the server receives
- Believes a same-as-shipping checkbox removes the need for tokens