Building Forms (<form>, <input>, <textarea>, <button>)

Forms collect user input and send it to a server or handle it with JavaScript.

Creating a Form (<form>)

  <form action="/submit-form" method="post">
    <!-- Form fields go here -->
</form>
  
Attribute Purpose
action URL that receives submitted data
method HTTP method: get (query string) or post (request body)
enctype Encoding — use multipart/form-data for file uploads
novalidate Disable browser validation (use custom JS validation instead)

For SPAs, often use method="post" with JavaScript preventDefault() and fetch API.

Input Types

HTML5 provides many input types with built-in validation and mobile keyboards:

  <label for="email">Email:</label>
<input type="email" id="email" name="email" required autocomplete="email">

<label for="age">Age:</label>
<input type="number" id="age" name="age" min="0" max="120">

<label for="birthday">Birthday:</label>
<input type="date" id="birthday" name="birthday">

<label for="color">Favorite color:</label>
<input type="color" id="color" name="color" value="#007bff">

<label for="file">Upload:</label>
<input type="file" id="file" name="file" accept="image/png,image/jpeg">
  

Radio Buttons and Checkboxes

  <fieldset>
    <legend>Shipping method</legend>
    <label><input type="radio" name="shipping" value="standard" checked> Standard</label>
    <label><input type="radio" name="shipping" value="express"> Express</label>
</fieldset>

<label><input type="checkbox" name="newsletter" value="yes"> Subscribe to newsletter</label>
  

Radio buttons sharing the same name are mutually exclusive. Checkboxes can be selected independently.

Select and Textarea

  <label for="country">Country:</label>
<select id="country" name="country" required>
    <option value="">Choose...</option>
    <option value="us">United States</option>
    <option value="uk">United Kingdom</option>
</select>

<label for="message">Message:</label>
<textarea id="message" name="message" rows="5" maxlength="500" placeholder="Enter your message"></textarea>
  

Buttons

  <button type="submit">Submit</button>
<button type="reset">Clear</button>
<button type="button" id="previewBtn">Preview</button>
  

Prefer <button type="submit"> over <input type="submit"> — buttons support HTML content and are more flexible.

Labels and Accessibility

Every input needs an associated label:

  <!-- Explicit association (preferred) -->
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>

<!-- Implicit association -->
<label>
    Remember me
    <input type="checkbox" name="remember">
</label>
  

Use <fieldset> and <legend> to group related controls. Never rely on placeholder text alone as a label.

HTML5 Validation Attributes

Attribute Effect
required Field must have a value
minlength / maxlength String length bounds
min / max / step Numeric/date constraints
pattern Regex validation
type="email" / type="url" Format validation
  <input type="text" name="username" pattern="[A-Za-z0-9_]{3,20}" title="3–20 alphanumeric characters">
  

Complete Example

  <form action="/api/contact" method="post" novalidate>
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" autocomplete="username" required>

    <label for="message">Message:</label>
    <textarea id="message" name="message" required></textarea>

    <button type="submit">Send</button>
</form>
  

Best Practices

  1. Use semantic typestype="email" gives better UX than plain text
  2. Set autocomplete — helps password managers and autofill
  3. Validate on server — never trust client-side validation alone
  4. Show clear errors — link messages with aria-describedby
  5. Disable submit while sending — prevent double submissions

Common Mistakes

Mistake Fix
Missing name attribute Data won’t appear in submission payload
Duplicate id values Breaks label association and JS selectors
<form> inside <form> Invalid HTML — merge or use separate forms
File upload without enctype Set enctype="multipart/form-data"

Troubleshooting

Form submits but server receives empty fields

  • Check every input has a name attribute
  • Verify method and action URL

Validation not working

  • Confirm required, type, and pattern are on the correct element
  • Custom JS may need to call form.checkValidity()

Mobile keyboard wrong for input

  • Use specific type values (email, tel, number, url)

Forms are the primary interface for user data — structure them accessibly, validate thoroughly, and handle errors gracefully.