Skip to main content
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

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>

Form Attributes

<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
<!-- 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
<form 
  action="/submit" 
  method="POST"
  autocomplete="on"
  novalidate
  target="_blank"
  enctype="multipart/form-data"
>
  <!-- Form fields -->
</form>
  • autocomplete: Enable/disable browser autofill (on or off)
  • novalidate: Disable HTML5 validation
  • target: Where to open response (_blank, _self, _parent, _top)
  • enctype: Encoding type
    • application/x-www-form-urlencoded (default)
    • multipart/form-data (required for file uploads)
    • text/plain

Input Types

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" />
<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

Number and Range Inputs

<!-- 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 and Time Inputs

<!-- 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" />

Checkboxes and Radio Buttons

<!-- 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)

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>

Other Input Types

<!-- 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>

Button Types

<!-- 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:
<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

Input Attributes

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" />

Complete Form Example

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

Build docs developers (and LLMs) love