The 20 HTML input types.
What each one does.
The type attribute on controls three things: the keyboard layout on mobile, the native validation, and the picker UI. Using the right type is free UX — the browser does work you'd otherwise have to write in JavaScript. This page is the complete reference: what each type triggers, what it validates, and when to pick it.
Short answer: Use type="email" for email (validates format, shows @ on mobile), type="tel" for phone (phone keypad, no format check), type="number" for quantities (spinners, numeric keyboard), type="date" for dates (calendar picker), type="file" for uploads. The type is a signal to the browser — better keyboard, better validation, better UX. Never use type="text" for everything.
✅ The complete list
Grouped by purpose.
Text-like inputs
type="text"
Any string. The fallback. Use only when no more specific type applies.
type="email"
Valid email format. Shows @ and . on mobile. Native validation blocks invalid formats.
type="tel"
Phone number. Shows phone keypad. No format validation — use pattern if needed.
type="url"
Full URL. Requires protocol (https://). Shows .com and / on mobile.
type="password"
Masked text. Dots instead of characters. No clipboard, no autocomplete (usually).
type="search"
Search input. iOS shows Search button. Some browsers show clear × inside the field.
Numeric inputs
type="number"
Numeric value. Spinners on desktop. Supports min, max, step. Rejects non-numeric input.
type="range"
Slider. Value is a number in [min, max]. No spinner. Good for volume, brightness, price filters.
Date and time inputs
type="date"
Calendar picker. Submits YYYY-MM-DD. Local date, no timezone.
type="time"
Time picker. Submits HH:MM (or with seconds). No date, no timezone.
type="datetime-local"
Date + time. Submits YYYY-MM-DDTHH:MM. Local time, no timezone.
type="month"
Year and month. Submits YYYY-MM. Good for credit card expiry.
type="week"
ISO week. Submits YYYY-Www. Rarely used — limited browser support.
Choice inputs
type="checkbox"
On/off. Multiple can be checked. Use a group with the same name for multi-select.
type="radio"
One of a group. Same name across the group — only one can be selected. Use required on any one to require a choice.
type="color"
Color picker. Submits hex like #ff6600. Supported by all modern browsers.
type="file"
File upload. Add multiple for multi-select, accept for file types. Requires enctype="multipart/form-data" on the form.
Button and hidden inputs
type="submit"
Submit button. Default type for <button> inside a form. Fires validation, sends the form.
type="reset"
Clears the form. Rarely used — surprising to users. Prefer a custom reset button.
type="button"
Plain button. No default action. Use for JS handlers that don't submit the form.
type="image"
Image submit. Like submit, but the button is an image. Sends click coordinates. Rarely used.
type="hidden"
Not visible. Submits a value with the form. Use for CSRF tokens, IDs. No validation.
✅ A complete form example
All the common types in one form.
type="email" → validates format, mobile @ key type="tel" → mobile phone keypad, no validation type="number" → numeric keyboard, spinners, min/max type="date" → calendar picker, submits YYYY-MM-DD type="color" → color picker, submits #rrggbb type="file" → file picker, needs enctype on form type="checkbox" → on/off, multi-select as a group type="radio" → one of group, same name, one value ⚠️ file input requires enctype="multipart/form-data" ⚠️ radio requires one option to be checked (required on one)
Don't use type="number" for phone numbers or credit cards. It looks right — numeric input, numeric keyboard — but type="number" adds spinner arrows, rejects leading zeros (breaks ZIP codes and card numbers), treats + as invalid, and rejects formatted values like (555) 123-4567. Use type="tel" for phone numbers and type="text" with inputmode="numeric" and a pattern for credit cards. The right type is about the data, not the keyboard.
⚠️ Common mistakes
The input-type mistakes that cost real time.
type="text" for everythingMissing all the native benefits. Fix: pick the type that matches the data.
type="number" for phone / credit cardBreaks leading zeros, rejects +. Fix: type="tel" or type="text" inputmode="numeric".
type="email" for usernameEnforces @ and domain — blocks valid usernames. Fix: type="text".
The form sends text-only — files are lost. Fix: enctype="multipart/form-data" on the form.
Each is its own group — all can be selected. Fix: same name across the group.
Server can't distinguish which were checked. Fix: give each a distinct value.
type="date" with a placeholderPlaceholders don't work on date inputs — the picker overrides. Fix: use a label instead.
type="submit" with JavaScript preventDefaultNo navigation, no fetch. Fix: remove preventDefault, or send the data in the handler.
❓ Frequently asked
What are the HTML input types?
HTML5 has 22 input types: text, email, tel, url, password, search, number, range, date, time, datetime-local, month, week, color, file, checkbox, radio, hidden, submit, reset, button, image. Each controls the keyboard layout (type=email shows @ on mobile), the native validation (type=email enforces @ and a domain), and the picker (type=date shows a calendar). Use the most specific type — text is the fallback, not the default choice.
What is the difference between type=text and type=email?
type=text accepts any string. type=email enforces a valid email format (local@domain), shows the @ and . keys on mobile keyboards, and enables native validation. If the user types not-an-email and submits, the browser blocks it with a message. For users' email addresses, always use type=email — the type is a signal to the browser, the mobile keyboard, and screen readers. It costs nothing and improves UX.
What is type=tel for?
type=tel is for telephone numbers. It does not validate format — phone number formats vary by country and there is no universal pattern the browser can enforce. Its main benefit is the mobile keyboard: type=tel shows the phone keypad (0-9, +, *, #). Use it with pattern if you need a specific format, and minlength/maxlength for length. Don't use type=number for phone numbers — it adds spinners and doesn't handle leading zeros or plus signs well.
When should I use type=number vs type=range?
Use type=number when the user needs to enter a specific numeric value (quantity, age, price). Use type=range when the user should pick from a continuous scale and precision doesn't matter (volume, brightness, price filter). Both support min, max, and step. type=number shows a text field with spinners and accepts keyboard input. type=range shows a slider and only allows values in the defined range. Pick based on whether the user knows the exact value they want.
What is type=search for?
type=search is semantically a search input. It renders like text on most browsers, but on iOS it shows a search keyboard with a Search button, and on some desktop browsers it shows a clear button (×) inside the field. The benefit is small but free: the browser knows this is a search field and adjusts accordingly. Use it for search forms. If you don't need the semantic hint, text works fine too.
What is the difference between type=date and type=datetime-local?
type=date shows a calendar picker for a date (year, month, day). type=datetime-local shows a date and a time picker — useful for scheduling events in the user's local timezone. Both submit a string like 2026-11-02 (date) or 2026-11-02T14:30 (datetime-local). Neither submits a timezone — the value is the user's local time. If you need UTC or a specific timezone, handle the conversion on the server or in JavaScript.