In Chapter 7, we learned the foundation of HTML forms:
<form>actionmethod<label><input>namevalueidGET vs POSTNow we move to the controls you'll see in real production forms.
Radio buttons allow the user to select one option from a group.
Example:
<label>
<input type="radio" name="gender" value="male">
Male
</label>
<label>
<input type="radio" name="gender" value="female">
Female
</label>
<label>
<input type="radio" name="gender" value="other">
Other
</label>It looks approximately like:
Gender
○ Male
○ Female
○ OtherThe important part is:
name="gender"All radio buttons that belong to the same group must have the same name.
name Matter for Radio Buttons?#Consider:
<input type="radio" name="gender" value="male">
<input type="radio" name="gender" value="female">Because both have:
name="gender"the browser treats them as one selection group.
The user can select:
○ Male
● Female
○ OtherBut if you accidentally do:
<input type="radio" name="male" value="male">
<input type="radio" name="female" value="female">they are treated as separate groups.
So the user could select both.
Same name
↓
Same radio group
↓
Normally one choicevalue of Radio Buttons#The visible text:
Maleis not necessarily the submitted value.
This:
<input
type="radio"
name="gender"
value="male"
>can produce:
gender=maleIf the user selects Female:
gender=femaleThat's why value is important.
checked#You can select a radio button by default.
<input
type="radio"
name="plan"
value="free"
checked
>
Free
<input
type="radio"
name="plan"
value="pro"
>
ProInitially:
● Free
○ Prochecked is a boolean attribute.
You don't need:
checked="true"Simply:
checkedis enough.
For related choices, use:
<fieldset>
<legend>Select your plan</legend>
<label>
<input
type="radio"
name="plan"
value="free"
>
Free
</label>
<label>
<input
type="radio"
name="plan"
value="pro"
>
Pro
</label>
<label>
<input
type="radio"
name="plan"
value="enterprise"
>
Enterprise
</label>
</fieldset>This is much more semantic and accessible.
We'll discuss <fieldset> and <legend> in detail later.
Checkboxes allow the user to select zero, one, or multiple options.
Example:
<label>
<input
type="checkbox"
name="skills"
value="html"
>
HTML
</label>
<label>
<input
type="checkbox"
name="skills"
value="css"
>
CSS
</label>
<label>
<input
type="checkbox"
name="skills"
value="javascript"
>
JavaScript
</label>Visual:
☐ HTML
☐ CSS
☐ JavaScriptThe user could select:
☑ HTML
☑ CSS
☐ JavaScriptThis is one of the most important distinctions.
| Radio | Checkbox |
|---|---|
| Usually one choice | Zero or multiple choices |
Same name creates group |
Multiple values can be selected |
type="radio" |
type="checkbox" |
| Example: payment method | Example: skills |
Think:
Radio:
Choose ONE
○ UPI
○ Card
○ Cashversus:
Checkbox:
Choose ANY
☑ HTML
☑ CSS
☐ JavaScriptchecked#<input
type="checkbox"
name="newsletter"
value="yes"
checked
>
Subscribe to newsletterInitially:
☑ Subscribe to newslettervalue#You may see:
<input
type="checkbox"
name="newsletter"
>This can submit a default value when checked.
However, for predictable application data, it's usually better to explicitly provide:
value="yes"Example:
<input
type="checkbox"
name="newsletter"
value="yes"
>Suppose:
<input
type="checkbox"
name="skills"
value="html"
>
<input
type="checkbox"
name="skills"
value="css"
>
<input
type="checkbox"
name="skills"
value="javascript"
>User selects HTML and JavaScript.
The submitted data can conceptually contain:
skills=html
skills=javascriptThis is an important concept:
Multiple controls can have the same
name.
This is especially common with checkbox groups.
A dropdown is created using:
<select>and:
<option>Example:
<label for="country">
Country
</label>
<select
id="country"
name="country"
>
<option value="india">India</option>
<option value="usa">United States</option>
<option value="uk">United Kingdom</option>
</select>Visual:
Country
┌──────────────────────┐
│ India ▼ │
└──────────────────────┘<option>#Each choice is represented by:
<option>Example:
<select name="country">
<option value="india">
India
</option>
<option value="usa">
United States
</option>
<option value="uk">
United Kingdom
</option>
</select>The visible text:
Indiaand submitted value:
indiacan be different.
selected#You can choose the initial option:
<select name="country">
<option value="india" selected>
India
</option>
<option value="usa">
United States
</option>
</select>Initially:
India ▼A common pattern is:
<select name="country" required>
<option value="" selected disabled>
Select a country
</option>
<option value="india">
India
</option>
<option value="usa">
United States
</option>
</select>This creates:
Select a country ▼The empty value:
value=""combined with:
requiredhelps prevent submitting the placeholder as a valid choice.
<optgroup>#You can group options.
Example:
<select name="city">
<optgroup label="India">
<option value="delhi">
Delhi
</option>
<option value="mumbai">
Mumbai
</option>
<option value="bangalore">
Bangalore
</option>
</optgroup>
<optgroup label="USA">
<option value="new-york">
New York
</option>
<option value="california">
California
</option>
</optgroup>
</select>Useful when there are many related choices.
A <select> can allow multiple selections.
<select
name="skills"
multiple
>
<option value="html">
HTML
</option>
<option value="css">
CSS
</option>
<option value="javascript">
JavaScript
</option>
<option value="react">
React
</option>
</select>Now the user can select multiple values.
Conceptually:
☑ HTML
☑ CSS
☐ JavaScript
☑ ReactThe actual UI depends on the browser/platform.
size with Multiple Select#You can control how many options are visibly displayed:
<select
name="skills"
multiple
size="4"
>For example:
┌──────────────────┐
│ HTML │
│ CSS │
│ JavaScript │
│ React │
└──────────────────┘<textarea> is used for multi-line text.
Example:
<label for="message">
Message
</label>
<textarea
id="message"
name="message"
rows="5"
cols="40"
></textarea>Visual:
Message
┌────────────────────────────┐
│ │
│ │
│ │
│ │
│ │
└────────────────────────────┘Typical use cases:
<input> vs <textarea>#<input> is generally single-line:
<input type="text"><textarea> supports multiple lines:
<textarea></textarea>For example:
Input:
[ Hello World ]
Textarea:
┌─────────────────────────┐
│ Hello World │
│ This is another line. │
│ And another line. │
└─────────────────────────┘rows and cols#You can provide an initial size:
<textarea
rows="6"
cols="50"
></textarea>However, in modern applications, visual sizing is commonly handled using CSS.
HTML provides the semantic control; CSS controls presentation.
<textarea>#Unlike <input>, textarea's initial content goes between the tags.
Correct:
<textarea>
Hello
</textarea>Don't use:
<textarea value="Hello"></textarea>textarea does not use a value attribute in the same way an <input> does.
This is a common interview question.
File selection uses:
<input type="file">Example:
<label for="resume">
Upload Resume
</label>
<input
type="file"
id="resume"
name="resume"
>Visual:
Upload Resume
[ Choose File ]You can provide hints about acceptable file types:
<input
type="file"
name="resume"
accept=".pdf,.doc,.docx"
>Or:
<input
type="file"
name="image"
accept="image/*"
>For images:
accept="image/*"can allow the browser's file picker to focus on image files.
accept is a hint to the user agent, not a security mechanism.
The server should still validate uploaded files.
You can allow multiple files:
<input
type="file"
name="documents"
multiple
>The user can select several files.
capture#On supported mobile browsers, capture can provide a hint to use a camera or microphone for certain capture scenarios.
Example:
<input
type="file"
accept="image/*"
capture
>Browser/platform behavior can vary.
Don't assume every browser will behave identically.
<fieldset> groups related controls.
Example:
<fieldset>
<legend>Personal Information</legend>
<label for="name">
Name
</label>
<input
id="name"
name="name"
type="text"
>
<label for="email">
Email
</label>
<input
id="email"
name="email"
type="email"
>
</fieldset>Conceptually:
┌─ Personal Information ─────────────┐
│ │
│ Name │
│ [________________________] │
│ │
│ Email │
│ [________________________] │
│ │
└────────────────────────────────────┘<legend>#<legend> provides the caption/name for the <fieldset>.
Example:
<fieldset>
<legend>Payment Method</legend>
...
</fieldset>This is especially valuable for groups such as:
Payment Method
○ UPI
○ Credit Card
○ Debit CardThe user needs to understand what the group represents.
A professional pattern:
<fieldset>
<legend>Payment Method</legend>
<label>
<input
type="radio"
name="payment"
value="upi"
>
UPI
</label>
<label>
<input
type="radio"
name="payment"
value="card"
>
Credit/Debit Card
</label>
<label>
<input
type="radio"
name="payment"
value="cash"
>
Cash
</label>
</fieldset>This creates a semantically meaningful group.
<datalist> provides suggested options for an input.
Example:
<label for="browser">
Browser
</label>
<input
list="browsers"
id="browser"
name="browser"
>
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
</datalist>The user can type and receive suggestions.
Conceptually:
Browser
┌──────────────────────┐
│ Chr │
└──────────────────────┘
Suggestions:
Chrome
ChromiumUnlike a strict <select>, the user isn't necessarily limited to the listed suggestions.
<select> vs <datalist>#<select> |
<datalist> |
|---|---|
| User chooses from defined options | Suggestions for an input |
| Usually restricts choices | User can generally enter another value |
| Dropdown control | Input + suggestions |
| Good for fixed categories | Good for suggestions/autocomplete |
Example:
Use:
<select>because the choices are defined.
Use:
<datalist>when free text plus suggestions makes sense.
A range slider can be created with:
<input type="range">Example:
<label for="volume">
Volume
</label>
<input
type="range"
id="volume"
name="volume"
min="0"
max="100"
value="50"
>Conceptually:
Volume
0 ─────────●──────────── 100
50min, max, and step#Example:
<input
type="range"
min="0"
max="100"
step="10"
>Possible values:
0
10
20
30
...
100Similarly, for numbers:
<input
type="number"
min="0"
max="100"
step="5"
>You can use:
<input type="color">Example:
<label for="theme">
Theme Color
</label>
<input
type="color"
id="theme"
name="theme"
value="#ff0000"
>The browser provides a color picker.
A hidden input isn't visible to the user:
<input
type="hidden"
name="user_id"
value="12345"
>This can be used for data that needs to travel with the form.
But there is a critical security rule:
Hidden does not mean secret.
A user can inspect HTML and modify hidden values.
Never trust:
<input
type="hidden"
name="role"
value="admin"
>as an authorization mechanism.
A malicious user could change:
adminto something else.
Authorization must happen on the server.
autocomplete#You can also set autocomplete on the entire form:
<form autocomplete="on">or:
<form autocomplete="off">However, browsers may make decisions based on user preferences and security considerations, so don't assume off will always prevent every form of autofill.
novalidate#HTML provides built-in constraint validation.
You can disable browser constraint validation for a form with:
<form novalidate>Example:
<form
action="/login"
method="post"
novalidate
>This can be useful when an application wants to implement its own validation UX.
But remember:
novalidate
≠
server validation is unnecessaryThe server should still validate important data.
form Attribute#A control doesn't always have to physically appear inside the <form> element.
Example:
<form id="user-form">
<input
type="text"
name="name"
>
</form>
<button
type="submit"
form="user-form"
>
Submit
</button>The button is outside the form in the HTML tree but is associated with:
form="user-form"This is useful in advanced layouts.
formaction#A submit button can override the form's action.
Example:
<form action="/save" method="post">
<input
type="text"
name="title"
>
<button type="submit">
Save
</button>
<button
type="submit"
formaction="/publish"
>
Publish
</button>
</form>Now:
Save
→ /save
Publish
→ /publishThis is an advanced but useful HTML capability.
formmethod#A submit button can also override the form's method.
<form
action="/process"
method="post"
>
<button type="submit">
Submit
</button>
<button
type="submit"
formmethod="get"
>
Preview
</button>
</form>Different submit buttons can therefore trigger different submission behavior.
Let's combine the major concepts.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
>
<title>Registration Form</title>
</head>
<body>
<h1>Create Account</h1>
<form
action="/register"
method="post"
enctype="multipart/form-data"
>
<!-- Personal Information -->
<fieldset>
<legend>Personal Information</legend>
<p>
<label for="name">
Full Name
</label>
<input
type="text"
id="name"
name="name"
autocomplete="name"
required
>
</p>
<p>
<label for="email">
Email
</label>
<input
type="email"
id="email"
name="email"
autocomplete="email"
required
>
</p>
<p>
<label for="phone">
Phone
</label>
<input
type="tel"
id="phone"
name="phone"
autocomplete="tel"
>
</p>
<p>
<label for="dob">
Date of Birth
</label>
<input
type="date"
id="dob"
name="dob"
>
</p>
</fieldset>
<!-- Gender -->
<fieldset>
<legend>Gender</legend>
<label>
<input
type="radio"
name="gender"
value="male"
>
Male
</label>
<label>
<input
type="radio"
name="gender"
value="female"
>
Female
</label>
<label>
<input
type="radio"
name="gender"
value="other"
>
Other
</label>
</fieldset>
<!-- Skills -->
<fieldset>
<legend>Skills</legend>
<label>
<input
type="checkbox"
name="skills"
value="html"
>
HTML
</label>
<label>
<input
type="checkbox"
name="skills"
value="css"
>
CSS
</label>
<label>
<input
type="checkbox"
name="skills"
value="javascript"
>
JavaScript
</label>
</fieldset>
<!-- Country -->
<p>
<label for="country">
Country
</label>
<select
id="country"
name="country"
required
>
<option
value=""
selected
disabled
>
Select a country
</option>
<option value="india">
India
</option>
<option value="usa">
United States
</option>
<option value="uk">
United Kingdom
</option>
</select>
</p>
<!-- About -->
<p>
<label for="about">
About You
</label>
<textarea
id="about"
name="about"
rows="5"
cols="40"
></textarea>
</p>
<!-- Resume -->
<p>
<label for="resume">
Resume
</label>
<input
type="file"
id="resume"
name="resume"
accept=".pdf,.doc,.docx"
>
</p>
<!-- Newsletter -->
<p>
<label>
<input
type="checkbox"
name="newsletter"
value="yes"
>
Subscribe to newsletter
</label>
</p>
<!-- Buttons -->
<button type="submit">
Create Account
</button>
<button type="reset">
Reset
</button>
</form>
</body>
</html>This is already much closer to a real-world HTML form.
enctype="multipart/form-data"?#Notice:
<form
method="post"
enctype="multipart/form-data"
>We used this because the form contains:
<input type="file">For file uploads, multipart/form-data is commonly required.
Conceptually:
Normal form
text fields
↓
encoded form data
File upload
text fields + files
↓
multipart/form-data
↓
serverWe'll explore this more when we cover advanced forms and file handling.
For production forms:
<label for="email">Email</label>
<input id="email"><fieldset>
<legend>Payment Method</legend>
</fieldset>type="email"
type="tel"
type="date"rather than making everything:
type="text"name#name="email"<input type="radio" name="male">
<input type="radio" name="female"><input type="radio" name="gender" value="male">
<input type="radio" name="gender" value="female">name#<input type="email" id="email"><input
type="email"
id="email"
name="email"
>value on textarea#<textarea value="Hello"></textarea><textarea>Hello</textarea><input
type="hidden"
name="role"
value="admin"
>Never use this as authorization.
<div> instead of semantic controls#Bad:
<div class="checkbox">
I agree
</div>Better:
<label>
<input
type="checkbox"
name="terms"
value="accepted"
>
I agree
</label>A very useful decision tree:
What does the user choose?
│
┌────────────┼─────────────┐
│ │ │
ONE MANY FREE TEXT
│ │ │
▼ ▼ ▼
Radio Checkbox Input
│
│
Many fixed options?
│
▼
SelectExamples:
Payment method
→ Radio
Skills
→ Checkbox
Country
→ Select
Comment
→ Textarea
Search with suggestions
→ Datalist| Element / Type | Purpose |
|---|---|
radio |
Select one option |
checkbox |
Select zero/multiple options |
<select> |
Choose from fixed options |
<option> |
Individual select option |
<optgroup> |
Group select options |
multiple |
Allow multiple selection |
<textarea> |
Multi-line text |
file |
Upload files |
<fieldset> |
Group related controls |
<legend> |
Label a control group |
<datalist> |
Provide input suggestions |
range |
Slider |
color |
Color picker |
hidden |
Non-visible form field |
checked |
Initially selected |
selected |
Initially selected <option> |
accept |
File type hint |
autocomplete |
Autofill hint |
novalidate |
Disable built-in form validation |
Radio is generally for one choice within a group; checkbox allows zero or multiple selections.
name?#The shared name groups them into the same selection group.
<fieldset>?#It semantically groups related form controls.
<legend>?#It provides the caption/name for a <fieldset>.
<select> and <datalist>?#select provides a defined set of choices, while datalist provides suggestions for an input while generally allowing free text.
<input
type="file"
multiple
>accept?#It provides a hint about which file types the user should select.
It is not a security mechanism.
multipart/form-data?#It is the standard form encoding used for forms that need to submit file data.
<textarea> content go?#Between the opening and closing tags:
<textarea>
Initial content
</textarea>checked do?#It specifies that a checkbox or radio button should initially be selected.
selected do?#It specifies an initially selected <option>.
No.
The user can inspect and modify it. Hidden fields must never be trusted for authorization or other security decisions.
Build a complete:
Job Application FormIt should contain:
Personal Information
├── Full Name
├── Email
├── Phone
├── Date of Birth
Professional Information
├── Experience
├── Current Role
├── Skills
│ ├── HTML
│ ├── CSS
│ ├── JavaScript
│ └── React
│
├── Preferred Location
│
└── Resume Upload
Employment Type
├── Full Time
├── Part Time
└── Contract
Additional Information
└── Cover Letter
☐ Subscribe to job alerts
[ Apply Now ]
[ Reset ]Try to use:
<form>
<fieldset>
<legend>
<label>
<input>
<select>
<option>
<textarea>
<button>without using CSS or JavaScript yet.
The goal is to make the HTML structure semantically correct first.
The most important thing to understand is that HTML forms aren't just collections of input boxes.
They are semantic data structures.
<form>
│
├── Group 1
│ ├── label
│ └── input
│
├── Group 2
│ ├── radio
│ └── radio
│
├── Group 3
│ ├── checkbox
│ └── checkbox
│
├── select
├── textarea
├── file
│
└── submitOnce you understand:
name
id
value
label
radio
checkbox
select
textarea
fieldset
legend
fileyou understand the core building blocks of almost every HTML form.
Next we'll learn how HTML validates user input without JavaScript:
requiredminmaxminlengthmaxlengthpatternsteptype validation:valid and :invalidcheckValidity()reportValidity()setCustomValidity()Mark it as complete to track your mastery.