C.W.K.
Stream
Lesson 02 of 04 · published

Input Types: The Right Tool For Each Question

~11 min · input-types, mobile-keyboards, validation

Level 0Markup Novice
0 XP0/34 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"The right input type isn't decoration — it summons the right keyboard, the right validation, the right autocomplete, the right hardware integration. All from one attribute."

Why Type Matters More Than You'd Think

Every type beyond the default text changes four things at once:

  1. The on-screen keyboard on mobile. type="email" shows the @ key without making the user toggle to symbols. type="tel" shows the numeric keypad. type="url" shows the / and .com keys.
  2. Built-in validation. type="email" rejects strings without an @; type="url" rejects malformed URLs; type="number" rejects non-numeric.
  3. Autocomplete. type="email" + autocomplete="email" tells the browser to offer the user's saved email. type="password" + autocomplete="new-password" triggers password manager generation.
  4. Hardware/OS integration. type="file" opens the OS file picker; type="color" opens the OS color picker; type="date" opens a date picker. No custom JS needed for any of these.

Text-Like Types

  • type="text" — default. Single-line text.
  • type="email" — single email (or comma-separated with multiple).
  • type="password" — masked input. Pair with autocomplete="current-password" for sign-in, "new-password" for sign-up.
  • type="url" — URL with validation.
  • type="tel" — telephone number. Note: no validation (phone formats vary too much globally); use pattern if you need format checking. The point is the mobile numeric keyboard.
  • type="search" — text input with a built-in clear-X button in some browsers.

Numeric And Range Types

  • type="number" — numeric input with up/down spinner. Use min, max, step for constraints. Note: not for credit cards or phone numbers (use text with inputmode="numeric" for those — number type strips leading zeros and won't allow non-numeric formatting).
  • type="range" — slider. Show the current value with a <output> element + JavaScript.

Date And Time Types

  • type="date" — YYYY-MM-DD. Opens native date picker.
  • type="datetime-local" — date + time, no timezone.
  • type="time" — HH:MM.
  • type="month", type="week" — for billing periods, sprints, etc.

The native date picker is wildly better than building one in JavaScript. Locale-aware, accessible, keyboard-navigable. Reach for a custom date picker only when you need calendar features the native one lacks (date ranges, custom highlighting).

Selection Types

  • type="checkbox" — independent on/off. Multiple in a group, multiple selectable.
  • type="radio" — mutually exclusive group. Same name ties them together; only one selectable.
  • type="file" — file picker. accept="image/*" filters; multiple allows multi-select; capture="environment" on mobile opens the camera.
  • type="color" — color picker. Value is a hex string.
  • type="hidden" — invisible, value sent with form. For CSRF tokens, IDs, etc.

Multi-Line And Dropdowns

<textarea> for multi-line text. rows and cols for default size; CSS for responsive sizing.

<select> + <option> for dropdowns. Use <optgroup label="..."> for grouped options. The default styling is platform-native and often ugly, which is why custom dropdowns exist — but custom dropdowns need full ARIA + keyboard + mobile work to match what <select> gives you for free. Memory rule: prefer native unless you can afford to do the full custom job.

The mobile keyboard is the lesson. If you ever wonder whether type="email" matters, hold a phone, tap a generic type="text" field, and try to type your email. Then compare to type="email". That single attribute is hours of cumulative user time across an app's lifetime.

inputmode: The Mobile-Only Keyboard Hint

Some fields are text by semantic but should show a numeric keyboard (a credit-card number, an OTP). inputmode hints at the keyboard without changing the type:

  • inputmode="numeric" — number pad, no validation, accepts non-numeric characters if needed.
  • inputmode="decimal" — number pad with a decimal point.
  • inputmode="tel" — phone keypad.
  • inputmode="email", "url", "search" — specialized keyboards.

Pippa's Note

Every input in Pippa's WebUI uses the right type. The chat input is type="text" but inputmode="text" with smart enter handling. The volume slider in settings is type="range" with a paired <output> showing the current value. The TTS voice file upload is type="file" accept="audio/*". None of these needed a third-party library — the platform already had the right tool.

Code

Every common type, properly attributed·html
<!-- Right type for each question -->
<label>Email <input type="email" name="email" autocomplete="email" /></label>
<label>Password <input type="password" name="password" autocomplete="current-password" /></label>
<label>Phone <input type="tel" name="phone" autocomplete="tel" /></label>
<label>Website <input type="url" name="website" autocomplete="url" /></label>

<label>Age <input type="number" name="age" min="13" max="120" step="1" /></label>
<label>
  Volume 
  <input type="range" name="volume" min="0" max="100" value="50"
         oninput="this.nextElementSibling.value = this.value" />
  <output>50</output>
</label>

<label>Date of birth <input type="date" name="dob" autocomplete="bday" /></label>
<label>Theme color <input type="color" name="theme" value="#5BA3D8" /></label>

<label>Profile photo <input type="file" name="photo" accept="image/*" /></label>
Text input + inputmode for numeric-but-not-number fields·html
<!-- Credit card with inputmode (not type=number!) -->
<label>
  Card number
  <input type="text"
         inputmode="numeric"
         pattern="[0-9 ]{13,19}"
         autocomplete="cc-number"
         name="card_number"
         maxlength="19" />
</label>
<!--
  Why not type="number"?
  - type="number" strips leading zeros
  - type="number" doesn't allow spaces or formatting
  - type="number" shows up/down spinner which is meaningless here
  inputmode="numeric" gives the mobile numeric keyboard without the bugs.
-->

<!-- OTP / one-time code -->
<label>
  Verification code
  <input type="text"
         inputmode="numeric"
         autocomplete="one-time-code"
         pattern="[0-9]{6}"
         maxlength="6"
         name="otp" />
</label>
<!-- autocomplete="one-time-code" lets iOS suggest the SMS code automatically -->
Grouped <select> options·html
<!-- Dropdown with optgroup -->
<label for="timezone">Timezone</label>
<select id="timezone" name="timezone">
  <optgroup label="Americas">
    <option value="America/New_York">New York</option>
    <option value="America/Los_Angeles">Los Angeles</option>
    <option value="America/Sao_Paulo">São Paulo</option>
  </optgroup>
  <optgroup label="Asia">
    <option value="Asia/Seoul">Seoul</option>
    <option value="Asia/Tokyo">Tokyo</option>
    <option value="Asia/Singapore">Singapore</option>
  </optgroup>
  <optgroup label="Europe">
    <option value="Europe/London">London</option>
    <option value="Europe/Berlin">Berlin</option>
  </optgroup>
</select>

External links

Exercise

Build a profile-edit form covering: display name (text), email (email), birthday (date), phone (tel), website (url), bio (textarea), profile photo (file, images only), theme color (color), notification level (range 0–100), favorite timezone (select with optgroups). Test it on a phone (or Chrome DevTools mobile emulator). Tap each field — does the right keyboard appear? Does autocomplete work? Does the file picker accept only images?
Hint
If the mobile keyboard shows the QWERTY for the phone field, you wrote type="text" instead of type="tel". If files of any type are selectable, you forgot accept="image/*".

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.