Day 7: Forms 2: Select, Textarea & Validation
✅ Today you will learn
- Dropdowns with select, option and optgroup
- Suggestions with datalist
- Multi-line text with textarea
- Group fields with fieldset and legend
- Built-in validation: required, min/max, maxlength, pattern
🏢 In the real world
Last week’s form brought 40 enquiries – but 9 had wrong mobile numbers and 5 forgot the event date. Today you make the browser itself refuse bad data before it is sent: no JavaScript needed.
Dropdowns: select and option
<label for="occasion">Occasion</label>
<select id="occasion" name="occasion" required>
<option value="">– Choose –</option>
<optgroup label="Family">
<option value="wedding">Wedding</option>
<option value="birthday">Birthday</option>
</optgroup>
<optgroup label="Festivals">
<option value="diwali" selected>Diwali</option>
<option value="rakhi">Raksha Bandhan</option>
</optgroup>
<option value="corporate">Corporate gifting</option>
</select>
<br><br>
<label for="boxes">Box sizes (Ctrl/⌘ for many)</label><br>
<select id="boxes" name="boxes" multiple size="3">
<option>250 g</option><option>500 g</option><option>1 kg</option>
</select>datalist: type or pick
<label for="city">Delivery city</label> <input id="city" name="city" list="cities" placeholder="Start typing…"> <datalist id="cities"> <option value="Jaipur"><option value="Ajmer"><option value="Kota"><option value="Udaipur"><option value="Jodhpur"> </datalist>
textarea for longer text
<label for="note">Special instructions</label><br> <textarea id="note" name="note" rows="4" cols="40" maxlength="200" placeholder="e.g. less sugar, Jain (no onion-garlic) namkeen"></textarea>
Grouping with fieldset and legend
<fieldset> <legend>Payment</legend> <label><input type="radio" name="pay" value="upi" checked> UPI</label> <label><input type="radio" name="pay" value="cash"> Cash on pickup</label> </fieldset> <fieldset disabled> <legend>Gift wrapping (coming soon)</legend> <label><input type="checkbox"> Add ribbon</label> </fieldset>
Built-in validation
| Attribute | Rule | Example |
|---|---|---|
| required | Must not be empty | <input required> |
| min / max | Number or date range | min="5" max="200" |
| step | Allowed increments | step="0.5" |
| minlength / maxlength | Text length | minlength="3" |
| pattern | Regular expression | pattern="[6-9][0-9]{9}" |
| type="email" / "url" | Format check | a@b.com |
| title | Shown as a hint with pattern errors | title="10-digit mobile" |
<form onsubmit="alert('All fields valid – would be sent!'); return false;">
<p><label>Name* <input name="name" required minlength="3"></label></p>
<p><label>Mobile* <input name="mobile" type="tel" required pattern="[6-9][0-9]{9}" title="10-digit Indian mobile starting with 6–9" placeholder="9829012345"></label></p>
<p><label>PIN code <input name="pin" pattern="[1-9][0-9]{5}" title="6-digit PIN code"></label></p>
<p><label>Quantity (kg)* <input name="qty" type="number" required min="5" max="200" step="0.5"></label></p>
<p><label>Event date* <input name="date" type="date" required min="2026-01-01"></label></p>
<button>Send enquiry</button>
</form>[6-9][0-9]{9} = first digit 6, 7, 8 or 9, then exactly nine more digits. The pattern must match the whole value. PIN code: [1-9][0-9]{5}.
Anyone can bypass HTML validation (DevTools, scripts). It improves the user experience; the server must still validate everything again.
More useful attributes
<form novalidate> <p><label>Order id <input value="BK-1042" readonly></label> (readonly – sent)</p> <p><label>Coupon <input value="DIWALI20" disabled></label> (disabled – NOT sent)</p> <p><label>Name <input name="n" autofocus autocomplete="name"></label></p> <p><label>OTP <input inputmode="numeric" autocomplete="one-time-code" maxlength="6"></label></p> </form>
Real example: the final enquiry form
<form action="https://httpbin.org/post" method="post" target="_blank">
<fieldset>
<legend>Your details</legend>
<p><label for="n">Name*</label><br><input id="n" name="name" required minlength="3" autocomplete="name"></p>
<p><label for="m">Mobile*</label><br><input id="m" name="mobile" type="tel" required pattern="[6-9][0-9]{9}" title="10-digit mobile" autocomplete="tel"></p>
</fieldset>
<fieldset>
<legend>Order</legend>
<p><label for="o">Occasion*</label><br>
<select id="o" name="occasion" required><option value="">– Choose –</option><option>Wedding</option><option>Diwali</option><option>Corporate</option></select></p>
<p><label for="q">Quantity (kg)*</label><br><input id="q" name="qty" type="number" min="5" max="200" step="0.5" required></p>
<p><label for="d">Event date*</label><br><input id="d" name="event_date" type="date" required></p>
<p><label for="t">Notes</label><br><textarea id="t" name="notes" rows="3" maxlength="300"></textarea></p>
</fieldset>
<p><label><input type="checkbox" name="consent" required> I agree to be contacted on WhatsApp</label></p>
<button type="submit">Send enquiry</button>
</form>🏅 Job skills unlocked today
Practice tasks
🏋️ Practice – do it yourself
Show solution
<form onsubmit="alert('Thanks!'); return false;">
<p><label>Rating <select name="rating" required><option value="">–</option><option>5</option><option>4</option><option>3</option><option>2</option><option>1</option></select></label></p>
<p><label>Comment<br><textarea name="comment" minlength="10" maxlength="300" required rows="3"></textarea></label></p>
<p><label>E-mail <input type="email" name="email" required></label></p>
<button>Send</button>
</form>Show solution
<input name="vehicle" pattern="[A-Z]{2}[0-9]{2}[A-Z]{1,2}[0-9]{4}" title="e.g. RJ14AB1234" placeholder="RJ14AB1234">Quick quiz
🧠 Quick Quiz – test yourself
Interview corner
💼 Interview Corner
Client-side vs server-side validation?
Client-side (HTML/JS) gives instant feedback and reduces bad requests; server-side is mandatory for security and data integrity because client checks can be bypassed.
How do you make form errors accessible?
Use labels, describe rules up front (aria-describedby), show clear text messages near the field, do not rely on colour alone, and move focus to the first error.
Summary
- select/option/optgroup for fixed choices; datalist for suggestions.
- textarea for long text; fieldset + legend to group.
- required, min/max, step, minlength/maxlength, pattern validate in the browser.
- Always validate again on the server.
Day 8: semantic HTML5 layout – header, nav, main, section, article, aside and footer.
