< input >
The input element: twenty-two types, one tag
A family of native form controls, each with behavior the browser has refined over decades. The type attribute is not cosmetic. Changing type="text" to type="email" is not a label change. It swaps the keyboard on mobile, enables built-in validation, changes the autofill category, and tells assistive technology the semantic kind of the field. The input element is the clearest example of how much the browser already does that does not need to be rebuilt.
Because the input element covers twenty-two types, this page is a map of the territory rather than a full tour. Each type will have its own page in this reference. What follows is what is shared across types, what the type attribute buys, and the surprising capabilities present across many of them.
The type attribute selects a different element, effectively
Each value of type gives the input a different UI, a different validation rule, a different virtual keyboard on mobile, a different autofill category, and a different value format. The twenty-two types fall into a handful of families:
- Text family:
text,search,email,url,tel,password - Numeric:
number,range - Date and time:
date,time,datetime-local,month,week - Selection:
checkbox,radio - Buttons:
submit,reset,button,image - File:
file - Hidden:
hidden - Color:
color
Each will get its own page. What follows are the attributes and behaviors that cut across many of them.
Built-in with native HTML
Across the input family, the browser provides:
- Virtual keyboard selection on mobile appropriate to the type, with no extra attribute.
- Validation UI that matches the platform, including the error bubble, the focus-on-submit-of-first-invalid behavior, and localized messages.
- Autofill integration when
autocompleteis set with standard tokens. - Password manager integration when
autocomplete="new-password"orautocomplete="current-password"is used. - SMS one-time-code integration when
autocomplete="one-time-code"is used. - Spellcheck, autocapitalize, and autocorrect defaults that match the semantic kind of the field.
- Constraint validation API on every input, covered on the form element page.
- Read-only and disabled states with correct announcement to assistive technology.
- Form participation, meaning the value serializes into
FormDataby name when the form is submitted.
Autofill is a specification, not a suggestion
The autocomplete attribute accepts a standardized set of tokens defined in the HTML specification. Values like name, given-name, family-name, email, tel, street-address, postal-code, country, cc-number, cc-exp, cc-csc, and bday are not arbitrary strings. They are a vocabulary the browser's autofill database maps to. Using the correct tokens means a user's saved addresses, credit cards, and contact info populate correctly and automatically.
For one-time codes from SMS: autocomplete="one-time-code". On iOS and Android this surfaces the verification code directly from the SMS keyboard suggestion strip, without the user leaving the app to copy it.
For new passwords: autocomplete="new-password". This signals to password managers to offer generation rather than retrieval.
Getting autocomplete wrong is one of the highest-friction parts of any sign-up or checkout flow, and it is entirely a matter of setting the right attribute values.
The inputmode attribute, separately
inputmode is independent from type and controls only the virtual keyboard on mobile:
numericgives digits only, no decimal.decimalgives digits with a decimal separator.telgives a phone keypad.emailgives a keyboard with@and..urlgives a keyboard with/and..searchshows a "search" button instead of "enter".noneshows no virtual keyboard, for cases where a custom one is being used.
A common pairing is type="text" inputmode="numeric" for a value that is numeric in nature but should not use type="number" (which has spinners, scroll-to-change behavior, and locale quirks for decimals). Postal codes, verification codes, and credit-card-number-like fields are usually this combination.
The pattern attribute: regex validation
pattern takes a regular expression that the value must fully match. Combined with title, the browser shows a meaningful error when the pattern fails:
<input type="text"
pattern="[A-Z]{2}[0-9]{6}"
title="Two uppercase letters followed by six digits"
name="reference-code">
The pattern is evaluated against the entire value (as if anchored with ^ and $). It participates in constraint validation, so :invalid and :user-invalid apply when the pattern does not match.
List-based autocomplete with <datalist>
The list attribute points at a <datalist> element, producing a native autocomplete dropdown:
<input type="text" list="countries" name="country">
<datalist id="countries">
<option value="Canada">
<option value="Mexico">
<option value="United States">
</datalist>
This is the native "combobox-lite" pattern. The user can type freely or pick from the list. It works on every input type that accepts a list, which includes most text-family and numeric types. For a true combobox with rich items and filtering, or where the list is long enough to need virtualization, a custom control is warranted. For the common "suggest common values" case, <datalist> is the answer.
File input, quietly capable
<input type="file"> accepts several attributes many authors never touch:
multipleallows selecting more than one file.acceptis a comma-separated list of MIME types or extensions.accept="image/*"on mobile opens the camera and photo library.accept=".pdf,.docx"restricts the picker.accept="image/png,image/jpeg"is the stricter form.captureon mobile requests the camera or microphone directly.capture="environment"for the rear camera.capture="user"for the front.
A file input's value is a FileList. Once the user selects files, each File object has a name, size, type, last-modified timestamp, and can be read as text, binary, or a data URL through the FileReader API, or streamed.
Drag-and-drop uploads can be built on top of a file input by styling the input to cover a drop zone and listening for the change event. No third-party upload library is required for the core interaction.
Range: a slider with an API
<input type="range"> is a native slider:
min,max,stepdefine the numeric bounds.valueis the current value.- Keyboard handling covers arrow keys, Page Up and Page Down, Home, and End. All native.
Styling is done through ::-webkit-slider-thumb and ::-webkit-slider-runnable-track, along with the Firefox equivalents. A two-handle range slider is the common case the native element does not cover. For single-handle, the native one is complete.
Paired with a <datalist>, a range input can display tick marks at specified values:
<input type="range" min="0" max="100" step="10" list="ticks">
<datalist id="ticks">
<option value="0"><option value="25"><option value="50"><option value="75"><option value="100">
</datalist>
Color: a native color picker
<input type="color"> opens the operating system color picker. The value is a seven-character hex string (#rrggbb). For many in-app "theme color" or "highlight" selections, this is sufficient and integrates with the user's OS-level color tools.
Date and time: a native date picker
The date and time types open native pickers: calendar UIs on desktop and native date rollers on mobile. They handle locale formatting automatically. The user sees dates in their own format, the value submitted is always in ISO 8601. This is exactly what a form wants: locale-friendly display, standardized data.
The tradeoff is styling. The native date picker cannot be fully restyled. For most applications (booking, scheduling, filtering by date), the native picker is functional, accessible, and built in.
Checkbox and radio: the semantics
Checkboxes and radios are frequently rebuilt as custom components for styling reasons, and that is where accessibility regressions most often enter a codebase. The native ones have:
- Correct roles and states announced to assistive tech.
- Keyboard handling where Space toggles, and arrow keys move between radios in a group.
- Form participation, so checked radios and checkboxes serialize into FormData by name.
- Indeterminate state on checkboxes, settable through JavaScript (
checkbox.indeterminate = true), useful for tri-state "select all" controls.
Modern CSS, including accent-color, appearance, and ::before/::after on labels, covers most styling needs without replacing the input. When custom visuals are required, the pattern is to visually hide the input (not display: none, which removes it from the tab order) and style a sibling element based on :checked and :focus-visible:
<label class="checkbox">
<input type="checkbox">
<span class="check"></span>
<span class="label">Accept terms</span>
</label>
.checkbox input { position: absolute; opacity: 0; }
.checkbox input:checked + .check { /* checked style */ }
.checkbox input:focus-visible + .check { /* focus style */ }
This keeps the native element in the accessibility tree, keeps keyboard and form participation intact, and still allows full visual design.
Readonly, disabled, and the difference
readonlymeans the value cannot be edited, but the field is focusable, selectable, and submits with the form.disabledmeans the field is inert, not focusable, and does not submit with the form.
Use readonly for values the user should see and can copy but not change, like a generated ID or a computed total. Use disabled for controls that are not currently applicable.
Composite patterns across inputs
- Address forms. Each field gets its specific autocomplete token. The browser fills in saved addresses in one tap.
- Payment forms.
cc-number,cc-exp,cc-csc,cc-name. Works with stored cards on iOS, Android, and desktop browsers. - Verification code entry.
autocomplete="one-time-code"paired withinputmode="numeric"andpattern="[0-9]{6}". The code appears on the keyboard suggestion bar on mobile. - Search with suggestions.
type="search"with a linked<datalist>. Native clear button, native autocomplete. - "Other, please specify." A radio group with one option revealing an input through CSS only, using
:has()on the parent form.
Already HTML-available
Patterns that HTML handles natively, which are often rebuilt in JavaScript:
- Custom date pickers for standard date selection where a native one would serve.
- Custom checkbox components built as divs with click handlers, which lose keyboard and form participation.
- JavaScript-based autocomplete for small, known value sets, where
<datalist>does the job. - Regex validation in JavaScript for field-level format checking, where
patterndoes the same thing and integrates with the rest of constraint validation. - Custom "clear" buttons on search inputs, where
type="search"provides one. - Custom upload widgets where the styling was the only reason the file input was replaced.
- Manual SMS code entry where
autocomplete="one-time-code"would surface the code from the keyboard. - Custom password strength or generation helpers where
autocomplete="new-password"triggers the built-in password manager flow.
Reference:
- WHATWG
- the-input-element
- the inputmode attribute
- caniuse.com
- mdn-html_elements_input
- MDN Docs
- Web/HTML/Element/input
- autocomplete attribute values