Forms & Input Types
HTML5 forms have powerful built-in validation, diverse input types, and accessibility features. Using the right input type gives you free mobile keyboard optimization, native UX, and client-side validation without JavaScript.
Form Structure & Attributes
<form
action="/api/register"
method="POST"
enctype="multipart/form-data" <!-- Required for file uploads -->
novalidate <!-- Disable browser validation (use your own) -->
autocomplete="on"
aria-label="User registration form"
>
<!-- fieldset groups related inputs; legend labels the group -->
<fieldset>
<legend>Personal Information</legend>
<!-- label must reference input via for/id OR wrap the input -->
<label for="full-name">Full Name <span aria-hidden="true">*</span></label>
<input
type="text"
id="full-name"
name="fullName"
required
minlength="2"
maxlength="100"
autocomplete="name"
placeholder="Jane Doe"
aria-required="true"
aria-describedby="name-hint name-error"
>
<span id="name-hint" class="hint">First and last name</span>
<span id="name-error" role="alert" class="error" hidden>Name is required</span>
</fieldset>
<!-- Submit button -->
<button type="submit">Create Account</button>
<button type="reset">Clear Form</button>
<button type="button" id="preview-btn">Preview</button>
</form>All Input Types
<!-- Text inputs -->
<input type="text" name="username"> <!-- Plain text -->
<input type="email" name="email" multiple> <!-- Validates email format; "email" keyboard on mobile -->
<input type="password" name="pwd" autocomplete="new-password">
<input type="search" name="q"> <!-- With clear button on some browsers -->
<input type="url" name="website"> <!-- Validates URL format -->
<input type="tel" name="phone" pattern="[0-9]{10}"> <!-- Numeric keyboard on mobile -->
<!-- Numeric -->
<input type="number" name="qty" min="1" max="100" step="1">
<input type="range" name="vol" min="0" max="100" step="5" value="50">
<!-- Date/Time -->
<input type="date" name="birthday" min="1900-01-01" max="2025-12-31">
<input type="time" name="start" min="09:00" max="17:00" step="900"> <!-- 15min steps -->
<input type="datetime-local" name="event"> <!-- Date + time, no timezone -->
<input type="month" name="exp"> <!-- YYYY-MM -->
<input type="week" name="week"> <!-- YYYY-W## -->
<!-- Selectors -->
<input type="color" name="brand-color" value="#ff6600">
<input type="file" name="avatar" accept="image/png,image/jpeg" multiple>
<!-- Checkboxes & Radios -->
<input type="checkbox" name="agree" id="agree" required>
<input type="radio" name="plan" value="free" checked>
<input type="radio" name="plan" value="pro">
<!-- Hidden & Submit -->
<input type="hidden" name="csrf_token" value="abc123">
<input type="submit" value="Submit">
<input type="image" src="/btn.png" alt="Submit order"> <!-- Image submit button -->
<input type="reset">Validation Attributes
<!-- Built-in validation - no JS needed -->
<input
type="email"
required <!-- Must not be empty -->
minlength="5" <!-- Min character count -->
maxlength="254" <!-- Max character count -->
pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$" <!-- Regex pattern -->
title="Please enter a valid email address" <!-- Shown in browser tooltip on invalid -->
>
<input type="number" min="0" max="999" step="0.01"> <!-- Numeric range + increment -->
<input type="file" accept=".pdf,.doc,.docx" multiple> <!-- File type filter -->
<input type="url" pattern="https://.*"> <!-- HTTPS only -->
<!-- Custom validation message via JS -->
<input type="email" id="email" oninvalid="this.setCustomValidity('Enter a valid email')" oninput="this.setCustomValidity('')">
<!-- Constraint Validation API -->
<script>
const form = document.querySelector('form');
form.addEventListener('submit', e => {
if (!form.checkValidity()) {
e.preventDefault();
// reportValidity() shows browser tooltips
form.reportValidity();
}
});
// Check individual input
const email = document.getElementById('email');
console.log(email.validity.typeMismatch); // true if wrong type
console.log(email.validity.valueMissing); // true if required + empty
console.log(email.validationMessage); // browser message string
</script>Select, Textarea, Datalist
<!-- Select dropdown -->
<label for="country">Country</label>
<select id="country" name="country" required autocomplete="country">
<option value="">-- Select a country --</option>
<optgroup label="North America">
<option value="US">United States</option>
<option value="CA">Canada</option>
<option value="MX">Mexico</option>
</optgroup>
<optgroup label="Europe">
<option value="GB" selected>United Kingdom</option>
<option value="DE">Germany</option>
</optgroup>
</select>
<!-- Multiple select -->
<select name="skills" multiple size="5">
<option value="js">JavaScript</option>
<option value="ts">TypeScript</option>
<option value="react">React</option>
</select>
<!-- Textarea -->
<label for="bio">Bio</label>
<textarea
id="bio"
name="bio"
rows="4"
cols="50"
minlength="20"
maxlength="500"
placeholder="Tell us about yourself..."
autocomplete="off"
spellcheck="true"
></textarea> <!-- Note: no space between tags - whitespace is content -->
<!-- Datalist: free-text input with suggestions (not a constraint) -->
<label for="framework">Framework</label>
<input list="frameworks" id="framework" name="framework">
<datalist id="frameworks">
<option value="React">
<option value="Vue">
<option value="Angular">
<option value="Svelte">
<option value="Next.js">
</datalist>Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free