Forms are essential for collecting user input, from simple search boxes to complex registration forms. HTML provides a rich set of form elements and input types.
The <form> element groups input elements and defines how data is submitted:
< form class = "header__search-form" action = "/buscar" method = "GET" >
< input
type = "search"
class = "header__search-input"
placeholder = "Buscar productos, marcas y más..."
name = "q"
id = "search-input"
autocomplete = "off"
/>
< button type = "submit" class = "header__search-button" aria-label = "Buscar" >
< svg > <!-- Search icon --> </ svg >
</ button >
</ form >
action - Where to Send Data
< form action = "/submit" method = "POST" >
<!-- Form fields -->
</ form >
Purpose : URL where form data is sent
Absolute URL: https://api.example.com/submit
Relative URL: /submit, /api/contact
Empty or omitted: Submits to current page
method - How to Send Data
<!-- GET method: data in URL -->
< form action = "/search" method = "GET" >
< input name = "q" value = "laptops" />
<!-- Submits to: /search?q=laptops -->
</ form >
<!-- POST method: data in request body -->
< form action = "/login" method = "POST" >
< input name = "email" type = "email" />
< input name = "password" type = "password" />
<!-- Data sent in request body, not visible in URL -->
</ form >
GET method :
Data appears in URL: ?key=value&key2=value2
Used for search forms, filters
Bookmarkable URLs
Limited data size
Not secure for sensitive data
POST method :
Data in request body (not in URL)
Used for login, registration, data modification
No data size limit
Better for sensitive information
Not bookmarkable
HTML5 provides many input types with built-in validation and specialized keyboards on mobile devices.
Text Inputs
<!-- Basic text -->
< input type = "text" name = "name" placeholder = "Your name" />
<!-- Email (validates format) -->
< input type = "email" name = "email" placeholder = "[email protected] " />
<!-- Password (hidden characters) -->
< input type = "password" name = "password" placeholder = "Password" />
<!-- Search (optimized for search) -->
< input type = "search" name = "q" placeholder = "Search..." />
<!-- Telephone -->
< input type = "tel" name = "phone" placeholder = "(555) 123-4567" />
<!-- URL -->
< input type = "url" name = "website" placeholder = "https://example.com" />
type='text'
type='email'
type='password'
type='search'
< input
type = "text"
name = "username"
placeholder = "Enter username"
required
minlength = "3"
maxlength = "20"
/>
Use for : Names, usernames, general textValidation attributes :
minlength: Minimum character count
maxlength: Maximum character count
pattern: Regular expression validation
required: Must be filled
< input
type = "email"
name = "email"
placeholder = "[email protected] "
required
multiple
/>
Use for : Email addressesFeatures :
Validates email format automatically
Shows email keyboard on mobile
multiple: Allow multiple emails (comma-separated)
Valid formats :< input
type = "password"
name = "password"
placeholder = "Password"
required
minlength = "8"
autocomplete = "current-password"
/>
Use for : Passwords, PINsFeatures :
Hides characters (shows dots or asterisks)
Prevents copy/paste (browser dependent)
Autocomplete values :
new-password: For registration
current-password: For login
< input
type = "search"
name = "q"
placeholder = "Search products..."
autocomplete = "off"
/>
Use for : Search boxesFeatures :
Shows “x” clear button in some browsers
May show search history
Optimized search keyboard on mobile
<!-- Number input -->
< input
type = "number"
name = "quantity"
min = "1"
max = "100"
step = "1"
value = "1"
/>
<!-- Range slider -->
< input
type = "range"
name = "volume"
min = "0"
max = "100"
step = "5"
value = "50"
/>
Number attributes :
min: Minimum value
max: Maximum value
step: Increment/decrement step
value: Default value
<!-- Date picker -->
< input type = "date" name = "birthday" min = "1900-01-01" max = "2024-12-31" />
<!-- Time picker -->
< input type = "time" name = "appointment" />
<!-- Date and time -->
< input type = "datetime-local" name = "event" />
<!-- Month picker -->
< input type = "month" name = "start-month" />
<!-- Week picker -->
< input type = "week" name = "week" />
<!-- Single checkbox -->
< label >
< input type = "checkbox" name = "subscribe" value = "yes" />
Subscribe to newsletter
</ label >
<!-- Multiple checkboxes (same name) -->
< fieldset >
< legend > Select categories: </ legend >
< label >
< input type = "checkbox" name = "categories" value = "electronics" />
Electronics
</ label >
< label >
< input type = "checkbox" name = "categories" value = "clothing" />
Clothing
</ label >
< label >
< input type = "checkbox" name = "categories" value = "books" checked />
Books
</ label >
</ fieldset >
Use for : Multiple selections, opt-insAttributes :
checked: Pre-selected
value: Value when checked
Multiple checkboxes can share a name (array in backend)
< fieldset >
< legend > Shipping method: </ legend >
< label >
< input type = "radio" name = "shipping" value = "standard" checked />
Standard (5-7 days)
</ label >
< label >
< input type = "radio" name = "shipping" value = "express" />
Express (2-3 days)
</ label >
< label >
< input type = "radio" name = "shipping" value = "overnight" />
Overnight
</ label >
</ fieldset >
Use for : Single selection from multiple optionsImportant :
Same name attribute groups radio buttons
Only one can be selected per group
Always provide a value attribute
File Upload
<!-- Single file -->
< input type = "file" name = "avatar" accept = "image/*" />
<!-- Multiple files -->
< input type = "file" name = "documents" multiple accept = ".pdf,.doc,.docx" />
<!-- Specific file types -->
< input type = "file" name = "image" accept = "image/png, image/jpeg" />
accept attribute :
image/*: All image types
video/*: All video types
audio/*: All audio types
.pdf: Specific extension
image/png, image/jpeg: Specific MIME types
Remember : When using file uploads, the form must have enctype="multipart/form-data"< form action = "/upload" method = "POST" enctype = "multipart/form-data" >
< input type = "file" name = "photo" />
< button type = "submit" > Upload </ button >
</ form >
<!-- Color picker -->
< input type = "color" name = "theme-color" value = "#3498db" />
<!-- Hidden field -->
< input type = "hidden" name = "user-id" value = "12345" />
Textarea
For multi-line text input:
< textarea
name = "message"
rows = "5"
cols = "50"
placeholder = "Enter your message..."
maxlength = "500"
required
></ textarea >
Attributes :
rows: Visible height (number of lines)
cols: Visible width (number of characters)
maxlength: Maximum character count
wrap: How text wraps (soft, hard)
Select Dropdown
<!-- Simple select -->
< select name = "country" required >
< option value = "" > Select a country </ option >
< option value = "us" > United States </ option >
< option value = "mx" > Mexico </ option >
< option value = "ca" > Canada </ option >
</ select >
<!-- With optgroups -->
< select name = "region" >
< 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 = "uk" > United Kingdom </ option >
< option value = "de" > Germany </ option >
< option value = "fr" > France </ option >
</ optgroup >
</ select >
<!-- Multiple selection -->
< select name = "interests" multiple size = "5" >
< option value = "tech" > Technology </ option >
< option value = "sports" > Sports </ option >
< option value = "music" > Music </ option >
< option value = "art" > Art </ option >
< option value = "travel" > Travel </ option >
</ select >
<!-- Submit button (submits form) -->
< button type = "submit" class = "btn btn--primary" >
Submit Form
</ button >
<!-- Regular button (does nothing, for JavaScript) -->
< button type = "button" class = "btn" onclick = " doSomething ()" >
Click Me
</ button >
<!-- Reset button (clears form) -->
< button type = "reset" class = "btn btn--secondary" >
Reset Form
</ button >
<!-- Input submit button -->
< input type = "submit" value = "Submit" />
<!-- Input button -->
< input type = "button" value = "Click" onclick = " alert ('Hi!')" />
Default type : Inside a <form>, buttons default to type="submit". Always specify the type explicitly to avoid confusion.
Labels and Accessibility
Proper labeling is crucial for accessibility:
Explicit Label
Implicit Label
ARIA Labels
< label for = "email-input" > Email Address: </ label >
< input
type = "email"
id = "email-input"
name = "email"
required
/>
Benefits :
Clicking label focuses the input
Screen readers associate label with input
for attribute matches input’s id
< label >
Email Address:
< input type = "email" name = "email" required />
</ label >
Benefits :
No need for id and for attributes
Input is nested inside label
Same accessibility benefits
<!-- For buttons with only icons -->
< button type = "submit" aria-label = "Search" >
< svg > <!-- Search icon --> </ svg >
</ button >
<!-- For inputs without visible labels -->
< input
type = "search"
name = "q"
placeholder = "Search products..."
aria-label = "Search products"
/>
Use when :
No visible label
Button contains only an icon
Placeholder isn’t enough context
Common Attributes
< input
type = "text"
name = "username"
id = "username-input"
value = "DefaultValue"
placeholder = "Enter username"
required
disabled
readonly
autocomplete = "username"
autofocus
/>
name: Field name (sent to server)
id: Unique identifier (for labels, JavaScript)
value: Default or current value
placeholder: Hint text (disappears when typing)
required: Field must be filled before submit
disabled: Field cannot be interacted with or submitted
readonly: Field can be seen but not edited (still submitted)
autocomplete: Browser autofill hint
autofocus: Automatically focus this field on page load
Validation Attributes
<!-- Required field -->
< input type = "text" name = "name" required />
<!-- Minimum and maximum length -->
< input type = "text" name = "username" minlength = "3" maxlength = "20" />
<!-- Pattern (regex) -->
< input
type = "text"
name = "zipcode"
pattern = "[0-9]{5}"
title = "5-digit zip code"
/>
<!-- Min and max (numbers/dates) -->
< input type = "number" name = "age" min = "18" max = "100" />
<!-- Step -->
< input type = "number" name = "price" step = "0.01" />
Here’s a comprehensive contact form:
< form class = "contact-form" action = "/submit-contact" method = "POST" >
<!-- Name field -->
< div class = "form-group" >
< label for = "name" > Full Name * </ label >
< input
type = "text"
id = "name"
name = "name"
required
minlength = "2"
placeholder = "John Doe"
/>
</ div >
<!-- Email field -->
< div class = "form-group" >
< label for = "email" > Email Address * </ label >
< input
type = "email"
id = "email"
name = "email"
required
placeholder = "[email protected] "
/>
</ div >
<!-- Phone field -->
< div class = "form-group" >
< label for = "phone" > Phone Number </ label >
< input
type = "tel"
id = "phone"
name = "phone"
placeholder = "(555) 123-4567"
/>
</ div >
<!-- Subject dropdown -->
< div class = "form-group" >
< label for = "subject" > Subject * </ label >
< select id = "subject" name = "subject" required >
< option value = "" > Select a subject </ option >
< option value = "general" > General Inquiry </ option >
< option value = "support" > Technical Support </ option >
< option value = "sales" > Sales </ option >
< option value = "feedback" > Feedback </ option >
</ select >
</ div >
<!-- Message textarea -->
< div class = "form-group" >
< label for = "message" > Message * </ label >
< textarea
id = "message"
name = "message"
rows = "5"
required
minlength = "10"
placeholder = "Enter your message here..."
></ textarea >
</ div >
<!-- Checkbox -->
< div class = "form-group" >
< label >
< input type = "checkbox" name = "subscribe" value = "yes" />
Subscribe to newsletter
</ label >
</ div >
<!-- Submit button -->
< div class = "form-group" >
< button type = "submit" class = "btn btn--primary" >
Send Message
</ button >
< button type = "reset" class = "btn btn--secondary" >
Clear Form
</ button >
</ div >
</ form >
Best Practices
Do
Always use labels for inputs
Use appropriate input types
Provide clear placeholder text
Add validation attributes
Use aria-label for icon buttons
Group related fields with <fieldset>
Mark required fields clearly
Don't
Don’t use placeholder as a label replacement
Don’t omit the name attribute
Don’t disable autocomplete without reason
Don’t use type="text" when specific types exist
Don’t forget enctype for file uploads
Don’t create forms without labels
Don’t use tables for form layout