> ## Documentation Index
> Fetch the complete documentation index at: https://devtools.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# HTML Forms

> Creating and working with HTML forms for user input

## Introduction to HTML Forms

HTML forms are a fundamental part of web development, allowing users to input data that can be processed by websites and web applications. Forms are used for everything from simple contact forms to complex multi-step registration processes, login systems, search interfaces, and more.

<Note>
  Forms are the primary way users interact with websites and provide information. Well-designed forms improve user experience and increase conversion rates.
</Note>

## Basic Form Structure

A basic HTML form consists of a `<form>` element containing various form controls like text fields, checkboxes, radio buttons, and buttons.

```html theme={null}
<form action="/submit-form" method="post">
  <div>
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" required>
  </div>
  
  <div>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>
  </div>
  
  <div>
    <label for="message">Message:</label>
    <textarea id="message" name="message" rows="4" required></textarea>
  </div>
  
  <button type="submit">Submit</button>
</form>
```

<Steps>
  <Step title="Form Element">
    The `<form>` element is the container for all form controls. It has attributes like `action` (where to send the data) and `method` (how to send it).
  </Step>

  <Step title="Form Controls">
    Elements like `<input>`, `<textarea>`, `<select>`, and `<button>` that collect user input.
  </Step>

  <Step title="Labels">
    The `<label>` element associates text with form controls, improving usability and accessibility.
  </Step>

  <Step title="Submit Button">
    A button with `type="submit"` that sends the form data to the server.
  </Step>
</Steps>

## Form Attributes

The `<form>` element has several important attributes:

<CardGroup cols={2}>
  <Card title="action" icon="paper-plane">
    Specifies where to send the form data when submitted. Can be a URL or a relative path.
  </Card>

  <Card title="method" icon="code-compare">
    Specifies the HTTP method to use when sending form data (get or post).
  </Card>

  <Card title="enctype" icon="file-export">
    Specifies how form data should be encoded when submitted (important for file uploads).
  </Card>

  <Card title="autocomplete" icon="sparkles">
    Specifies whether form controls should have autocomplete enabled.
  </Card>

  <Card title="novalidate" icon="triangle-exclamation">
    When present, it specifies that the form should not be validated when submitted.
  </Card>

  <Card title="target" icon="bullseye-arrow">
    Specifies where to display the response after submitting the form (\_self, \_blank, etc.).
  </Card>
</CardGroup>

```html theme={null}
<!-- Form that uploads files -->
<form action="/upload" method="post" enctype="multipart/form-data">
  <input type="file" name="document">
  <button type="submit">Upload</button>
</form>

<!-- Form that opens response in a new tab -->
<form action="/search" method="get" target="_blank">
  <input type="search" name="q">
  <button type="submit">Search</button>
</form>
```

## Input Types

The `<input>` element is the most versatile form control. Its behavior changes dramatically based on its `type` attribute.

### Text Input Types

```html theme={null}
<label for="name">Name:</label>
<input type="text" id="name" name="name" placeholder="Enter your name">

<label for="email">Email:</label>
<input type="email" id="email" name="email" placeholder="Enter your email">

<label for="password">Password:</label>
<input type="password" id="password" name="password">

<label for="comment">Comment:</label>
<textarea id="comment" name="comment" rows="4" cols="50"></textarea>
```

<CardGroup cols={2}>
  <Card title="text" icon="font">
    Basic single-line text input
  </Card>

  <Card title="email" icon="envelope">
    Input for email addresses with built-in validation
  </Card>

  <Card title="password" icon="lock">
    Input that masks characters as they're typed
  </Card>

  <Card title="textarea" icon="paragraph">
    Multi-line text input
  </Card>

  <Card title="search" icon="magnifying-glass">
    Input for search queries
  </Card>

  <Card title="tel" icon="phone">
    Input for telephone numbers
  </Card>

  <Card title="url" icon="link">
    Input for URLs with built-in validation
  </Card>
</CardGroup>

### Numeric Input Types

```html theme={null}
<label for="age">Age:</label>
<input type="number" id="age" name="age" min="0" max="120">

<label for="rating">Rating:</label>
<input type="range" id="rating" name="rating" min="1" max="5" step="1">

<label for="price">Price:</label>
<input type="number" id="price" name="price" min="0" step="0.01">
```

<CardGroup cols={2}>
  <Card title="number" icon="1">
    Input for numerical values with optional min/max/step
  </Card>

  <Card title="range" icon="sliders">
    Slider control for selecting a value from a range
  </Card>
</CardGroup>

### Date and Time Input Types

```html theme={null}
<label for="birthdate">Birth Date:</label>
<input type="date" id="birthdate" name="birthdate">

<label for="meeting-time">Meeting Time:</label>
<input type="datetime-local" id="meeting-time" name="meeting-time">

<label for="appointment">Appointment (date and time):</label>
<input type="datetime-local" id="appointment" name="appointment">

<label for="start-time">Start Time:</label>
<input type="time" id="start-time" name="start-time">

<label for="vacation-week">Vacation Week:</label>
<input type="week" id="vacation-week" name="vacation-week">

<label for="vacation-month">Vacation Month:</label>
<input type="month" id="vacation-month" name="vacation-month">
```

<CardGroup cols={2}>
  <Card title="date" icon="calendar-days">
    Input for a date (year, month, day)
  </Card>

  <Card title="time" icon="clock">
    Input for a time (hour, minute)
  </Card>

  <Card title="datetime-local" icon="calendar-clock">
    Input for a date and time
  </Card>

  <Card title="month" icon="calendar">
    Input for a month and year
  </Card>

  <Card title="week" icon="calendar-week">
    Input for a week and year
  </Card>
</CardGroup>

### Selection Input Types

```html theme={null}
<label for="color">Favorite Color:</label>
<input type="color" id="color" name="color">

<fieldset>
  <legend>Subscription:</legend>
  <div>
    <input type="radio" id="free" name="subscription" value="free" checked>
    <label for="free">Free</label>
  </div>
  <div>
    <input type="radio" id="premium" name="subscription" value="premium">
    <label for="premium">Premium</label>
  </div>
</fieldset>

<fieldset>
  <legend>Interests:</legend>
  <div>
    <input type="checkbox" id="coding" name="interests" value="coding">
    <label for="coding">Coding</label>
  </div>
  <div>
    <input type="checkbox" id="design" name="interests" value="design">
    <label for="design">Design</label>
  </div>
  <div>
    <input type="checkbox" id="music" name="interests" value="music">
    <label for="music">Music</label>
  </div>
</fieldset>

<label for="country">Country:</label>
<select id="country" name="country">
  <option value="">Select a country</option>
  <option value="us">United States</option>
  <option value="ca">Canada</option>
  <option value="mx">Mexico</option>
</select>

<label for="languages">Languages:</label>
<select id="languages" name="languages" multiple>
  <option value="html">HTML</option>
  <option value="css">CSS</option>
  <option value="js">JavaScript</option>
</select>
```

<CardGroup cols={2}>
  <Card title="color" icon="palette">
    Color picker control
  </Card>

  <Card title="radio" icon="circle-dot">
    Radio buttons for selecting one option from a group
  </Card>

  <Card title="checkbox" icon="square-check">
    Checkboxes for selecting multiple options
  </Card>

  <Card title="select" icon="list">
    Dropdown list for selecting one or multiple options
  </Card>
</CardGroup>

### File Input

```html theme={null}
<label for="profile-picture">Profile Picture:</label>
<input type="file" id="profile-picture" name="profile-picture" accept="image/*">

<label for="documents">Documents:</label>
<input type="file" id="documents" name="documents" multiple accept=".pdf,.doc,.docx">
```

<CardGroup cols={2}>
  <Card title="file" icon="file-arrow-up">
    Input for uploading files
  </Card>

  <Card title="accept" icon="file-check">
    Attribute to specify accepted file types
  </Card>

  <Card title="multiple" icon="copy">
    Attribute to allow multiple file selection
  </Card>
</CardGroup>

### Hidden Input

```html theme={null}
<input type="hidden" id="user-id" name="user-id" value="12345">
```

<Note>
  Hidden inputs are not displayed to the user but are included when the form is submitted. They're useful for passing data that the user doesn't need to see or modify.
</Note>

## Input Attributes

Input elements have many attributes that control their behavior and appearance:

<CardGroup cols={2}>
  <Card title="name" icon="signature">
    Specifies the name of the input, which is submitted with the form data
  </Card>

  <Card title="value" icon="input-text">
    Specifies the initial value of the input
  </Card>

  <Card title="placeholder" icon="i-cursor">
    Provides a hint about what to enter in the input
  </Card>

  <Card title="required" icon="asterisk">
    Specifies that the input must be filled out before submitting the form
  </Card>

  <Card title="disabled" icon="ban">
    Disables the input, preventing user interaction
  </Card>

  <Card title="readonly" icon="lock">
    Makes the input read-only, allowing it to be viewed but not modified
  </Card>

  <Card title="autofocus" icon="arrow-pointer">
    Automatically focuses the input when the page loads
  </Card>

  <Card title="autocomplete" icon="sparkles">
    Controls browser autocomplete behavior for the input
  </Card>

  <Card title="min/max" icon="arrows-left-right">
    Specifies minimum and maximum values for numeric inputs
  </Card>

  <Card title="pattern" icon="code">
    Specifies a regular expression that the input's value must match
  </Card>

  <Card title="step" icon="stairs">
    Specifies the interval between valid values for numeric inputs
  </Card>

  <Card title="maxlength" icon="text-width">
    Specifies the maximum number of characters allowed in the input
  </Card>
</CardGroup>

```html theme={null}
<input type="text" name="username" placeholder="Username" required autofocus>

<input type="email" name="email" value="user@example.com" readonly>

<input type="number" name="quantity" min="1" max="10" step="1" value="1">

<input type="text" name="zipcode" pattern="[0-9]{5}" placeholder="5-digit ZIP code">

<input type="password" name="password" minlength="8" maxlength="20" autocomplete="new-password">
```

## Buttons

Buttons are used to submit forms or trigger JavaScript actions:

```html theme={null}
<!-- Submit button -->
<button type="submit">Submit</button>

<!-- Reset button -->
<button type="reset">Reset</button>

<!-- Button for JavaScript actions -->
<button type="button" onclick="showAlert()">Click Me</button>

<!-- Image button -->
<button type="submit">
  <img src="submit-icon.png" alt=""> Submit
</button>

<!-- Old-style submit button -->
<input type="submit" value="Submit">
```

<CardGroup cols={2}>
  <Card title="submit" icon="paper-plane">
    Submits the form data
  </Card>

  <Card title="reset" icon="rotate-left">
    Resets all form controls to their initial values
  </Card>

  <Card title="button" icon="square">
    Does nothing by default, typically used with JavaScript
  </Card>
</CardGroup>

<Tip>
  The `<button>` element is more flexible than `<input type="submit">` because it can contain HTML content like images and formatted text.
</Tip>

## Form Organization

Well-organized forms are easier to use and understand. Use these elements to structure your forms:

### Fieldset and Legend

```html theme={null}
<form>
  <fieldset>
    <legend>Personal Information</legend>
    <div>
      <label for="first-name">First Name:</label>
      <input type="text" id="first-name" name="first-name">
    </div>
    <div>
      <label for="last-name">Last Name:</label>
      <input type="text" id="last-name" name="last-name">
    </div>
  </fieldset>
  
  <fieldset>
    <legend>Contact Information</legend>
    <div>
      <label for="email">Email:</label>
      <input type="email" id="email" name="email">
    </div>
    <div>
      <label for="phone">Phone:</label>
      <input type="tel" id="phone" name="phone">
    </div>
  </fieldset>
  
  <button type="submit">Submit</button>
</form>
```

<CardGroup cols={2}>
  <Card title="fieldset" icon="square-dashed">
    Groups related form controls together
  </Card>

  <Card title="legend" icon="heading">
    Provides a caption for the fieldset
  </Card>
</CardGroup>

### Datalist

The `<datalist>` element provides a list of predefined options for an input element, creating an autocomplete feature:

```html theme={null}
<label for="browser">Choose your browser:</label>
<input list="browsers" id="browser" name="browser">
<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
  <option value="Safari">
  <option value="Edge">
  <option value="Opera">
</datalist>
```

<Note>
  Unlike the `<select>` element, `<datalist>` allows users to enter values that aren't in the list, providing both flexibility and suggestions.
</Note>

### Output

The `<output>` element represents the result of a calculation or user action:

```html theme={null}
<form oninput="result.value = parseInt(a.value) + parseInt(b.value)">
  <input type="number" id="a" name="a" value="0"> +
  <input type="number" id="b" name="b" value="0"> =
  <output name="result" for="a b">0</output>
</form>
```

## Form Validation

Form validation ensures that user input is complete and in the correct format before submitting to the server.

### Built-in Validation

HTML5 provides built-in validation for many input types:

```html theme={null}
<form>
  <div>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>
    <!-- Validates that the input is a properly formatted email address -->
  </div>
  
  <div>
    <label for="website">Website:</label>
    <input type="url" id="website" name="website">
    <!-- Validates that the input is a properly formatted URL -->
  </div>
  
  <div>
    <label for="age">Age:</label>
    <input type="number" id="age" name="age" min="18" max="120">
    <!-- Validates that the input is a number between 18 and 120 -->
  </div>
  
  <div>
    <label for="phone">Phone:</label>
    <input type="tel" id="phone" name="phone" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" placeholder="123-456-7890">
    <!-- Validates that the input matches the specified pattern -->
  </div>
  
  <button type="submit">Submit</button>
</form>
```

<Warning>
  While HTML5 validation is convenient, it's not sufficient for security. Always validate form data on the server side as well.
</Warning>

### Custom Validation with JavaScript

For more complex validation requirements, you can use JavaScript:

```html theme={null}
<form id="registration-form" novalidate>
  <div>
    <label for="password">Password:</label>
    <input type="password" id="password" name="password" required>
  </div>
  
  <div>
    <label for="confirm-password">Confirm Password:</label>
    <input type="password" id="confirm-password" name="confirm-password" required>
    <span id="password-error" class="error"></span>
  </div>
  
  <button type="submit">Register</button>
</form>

<script>
  const form = document.getElementById('registration-form');
  const password = document.getElementById('password');
  const confirmPassword = document.getElementById('confirm-password');
  const passwordError = document.getElementById('password-error');
  
  form.addEventListener('submit', function(event) {
    // Check if passwords match
    if (password.value !== confirmPassword.value) {
      passwordError.textContent = 'Passwords do not match';
      event.preventDefault(); // Prevent form submission
    } else {
      passwordError.textContent = '';
    }
  });
</script>
```

<Tip>
  The `novalidate` attribute on the form disables the browser's built-in validation, allowing you to implement custom validation with JavaScript.
</Tip>

## Form Submission

Forms can be submitted in different ways:

### Traditional Form Submission

```html theme={null}
<form action="/submit" method="post">
  <!-- Form fields -->
  <button type="submit">Submit</button>
</form>
```

This causes the browser to navigate to the URL specified in the `action` attribute, sending the form data using the HTTP method specified in the `method` attribute.

### AJAX Form Submission

Using JavaScript, you can submit forms asynchronously without page navigation:

```html theme={null}
<form id="contact-form">
  <div>
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" required>
  </div>
  
  <div>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>
  </div>
  
  <div>
    <label for="message">Message:</label>
    <textarea id="message" name="message" required></textarea>
  </div>
  
  <button type="submit">Send</button>
  <div id="form-status"></div>
</form>

<script>
  const form = document.getElementById('contact-form');
  const formStatus = document.getElementById('form-status');
  
  form.addEventListener('submit', async function(event) {
    event.preventDefault(); // Prevent traditional form submission
    
    try {
      const formData = new FormData(form);
      const response = await fetch('/api/contact', {
        method: 'POST',
        body: formData
      });
      
      if (response.ok) {
        formStatus.textContent = 'Message sent successfully!';
        form.reset(); // Clear the form
      } else {
        formStatus.textContent = 'Error sending message. Please try again.';
      }
    } catch (error) {
      formStatus.textContent = 'Network error. Please try again later.';
      console.error('Error:', error);
    }
  });
</script>
```

## File Uploads

To handle file uploads, you need to set the form's `enctype` attribute to `multipart/form-data`:

```html theme={null}
<form action="/upload" method="post" enctype="multipart/form-data">
  <div>
    <label for="profile-picture">Profile Picture:</label>
    <input type="file" id="profile-picture" name="profile-picture" accept="image/*">
  </div>
  
  <div>
    <label for="resume">Resume:</label>
    <input type="file" id="resume" name="resume" accept=".pdf,.doc,.docx">
  </div>
  
  <button type="submit">Upload</button>
</form>
```

<Warning>
  File uploads can pose security risks. Always validate file types and sizes on the server side, and scan uploaded files for malware if possible.
</Warning>

## Styling Forms

Forms often need custom styling to match your website's design. Here's a basic example of styled form elements:

```html theme={null}
<style>
  .form-group {
    margin-bottom: 1rem;
  }
  
  label {
    display: block;
    margin-bottom: 0.5rem;
    font-weight: bold;
  }
  
  input[type="text"],
  input[type="email"],
  input[type="password"],
  textarea,
  select {
    width: 100%;
    padding: 0.5rem;
    border: 1px solid #ccc;
    border-radius: 4px;
    font-size: 1rem;
  }
  
  input[type="text"]:focus,
  input[type="email"]:focus,
  input[type="password"]:focus,
  textarea:focus,
  select:focus {
    border-color: #0066ff;
    outline: none;
    box-shadow: 0 0 0 3px rgba(0, 102, 255, 0.25);
  }
  
  .checkbox-group,
  .radio-group {
    display: flex;
    align-items: center;
    margin-bottom: 0.5rem;
  }
  
  .checkbox-group input,
  .radio-group input {
    margin-right: 0.5rem;
  }
  
  button {
    padding: 0.5rem 1rem;
    background-color: #0066ff;
    color: white;
    border: none;
    border-radius: 4px;
    font-size: 1rem;
    cursor: pointer;
  }
  
  button:hover {
    background-color: #0052cc;
  }
  
  .error-message {
    color: #d9534f;
    font-size: 0.875rem;
    margin-top: 0.25rem;
  }
</style>

<form>
  <div class="form-group">
    <label for="name">Name</label>
    <input type="text" id="name" name="name" required>
  </div>
  
  <div class="form-group">
    <label for="email">Email</label>
    <input type="email" id="email" name="email" required>
    <div class="error-message"></div>
  </div>
  
  <div class="form-group">
    <label>Subscription</label>
    <div class="radio-group">
      <input type="radio" id="free" name="subscription" value="free" checked>
      <label for="free">Free</label>
    </div>
    <div class="radio-group">
      <input type="radio" id="premium" name="subscription" value="premium">
      <label for="premium">Premium</label>
    </div>
  </div>
  
  <div class="form-group">
    <label>Interests</label>
    <div class="checkbox-group">
      <input type="checkbox" id="coding" name="interests" value="coding">
      <label for="coding">Coding</label>
    </div>
    <div class="checkbox-group">
      <input type="checkbox" id="design" name="interests" value="design">
      <label for="design">Design</label>
    </div>
  </div>
  
  <button type="submit">Submit</button>
</form>
```

## Accessibility in Forms

Accessible forms ensure that all users, including those with disabilities, can interact with your forms:

<CardGroup cols={2}>
  <Card title="Labels" icon="tags">
    Always use `<label>` elements properly associated with form controls
  </Card>

  <Card title="Fieldset & Legend" icon="square-dashed">
    Group related controls and provide a description
  </Card>

  <Card title="Error Messages" icon="circle-exclamation">
    Make error messages clear and associate them with the relevant fields
  </Card>

  <Card title="Focus Styles" icon="arrow-pointer">
    Ensure focus states are visible for keyboard navigation
  </Card>

  <Card title="ARIA Attributes" icon="universal-access">
    Use ARIA attributes when necessary to improve accessibility
  </Card>

  <Card title="Tab Order" icon="arrow-right">
    Ensure a logical tab order for keyboard navigation
  </Card>
</CardGroup>

```html theme={null}
<form>
  <div>
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" aria-required="true" aria-describedby="username-help">
    <p id="username-help">Your username must be 5-20 characters long.</p>
  </div>
  
  <div>
    <label for="password">Password:</label>
    <input type="password" id="password" name="password" aria-required="true" aria-describedby="password-error">
    <p id="password-error" role="alert" class="error"></p>
  </div>
  
  <button type="submit">Log In</button>
</form>
```

<Tip>
  The `aria-describedby` attribute associates help text or error messages with form controls, ensuring screen readers announce this information when the control is focused.
</Tip>

## Best Practices for HTML Forms

1. **Use appropriate input types** to take advantage of built-in validation and appropriate mobile keyboards
2. **Label all form controls** clearly and associate labels with inputs using the `for` attribute
3. **Group related fields** with `<fieldset>` and `<legend>`
4. **Provide clear error messages** that explain how to fix the problem
5. **Use placeholder text as hints**, not as replacements for labels
6. **Make forms keyboard accessible** by ensuring all controls can be navigated and operated with a keyboard
7. **Implement both client-side and server-side validation** for security
8. **Use autocomplete attributes** appropriately to help users fill forms faster
9. **Keep forms as short as possible** by only asking for necessary information
10. **Test forms on different devices and browsers** to ensure compatibility

<Warning>
  Never use the `autofocus` attribute on forms that appear below other content, as it can disorient users, especially those using screen readers. Use it only when the form is the primary content of the page.
</Warning>

## Common Form Patterns

### Login Form

```html theme={null}
<form action="/login" method="post">
  <div>
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" autocomplete="username" required>
  </div>
  
  <div>
    <label for="password">Password:</label>
    <input type="password" id="password" name="password" autocomplete="current-password" required>
  </div>
  
  <div>
    <input type="checkbox" id="remember" name="remember">
    <label for="remember">Remember me</label>
  </div>
  
  <button type="submit">Log In</button>
  
  <div>
    <a href="/forgot-password">Forgot password?</a>
  </div>
</form>
```

### Search Form

```html theme={null}
<form action="/search" method="get" role="search">
  <label for="search" class="visually-hidden">Search:</label>
  <input type="search" id="search" name="q" placeholder="Search..." required>
  <button type="submit" aria-label="Search">
    <svg aria-hidden="true" focusable="false" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
      <!-- Search icon SVG path -->
      <path d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"/>
    </svg>
  </button>
</form>
```

### Newsletter Signup

```html theme={null}
<form action="/subscribe" method="post">
  <div>
    <label for="email">Subscribe to our newsletter:</label>
    <input type="email" id="email" name="email" placeholder="Your email address" required>
  </div>
  
  <div>
    <input type="checkbox" id="terms" name="terms" required>
    <label for="terms">I agree to the <a href="/terms">terms and conditions</a></label>
  </div>
  
  <button type="submit">Subscribe</button>
</form>
```

### Multi-step Form

```html theme={null}
<form id="multi-step-form">
  <!-- Step 1: Personal Information -->
  <div class="form-step" id="step1">
    <h2>Personal Information</h2>
    
    <div>
      <label for="first-name">First Name:</label>
      <input type="text" id="first-name" name="first-name" required>
    </div>
    
    <div>
      <label for="last-name">Last Name:</label>
      <input type="text" id="last-name" name="last-name" required>
    </div>
    
    <button type="button" onclick="nextStep(1, 2)">Next</button>
  </div>
  
  <!-- Step 2: Contact Information -->
  <div class="form-step" id="step2" style="display: none;">
    <h2>Contact Information</h2>
    
    <div>
      <label for="email">Email:</label>
      <input type="email" id="email" name="email" required>
    </div>
    
    <div>
      <label for="phone">Phone:</label>
      <input type="tel" id="phone" name="phone">
    </div>
    
    <button type="button" onclick="nextStep(2, 1)">Previous</button>
    <button type="button" onclick="nextStep(2, 3)">Next</button>
  </div>
  
  <!-- Step 3: Review and Submit -->
  <div class="form-step" id="step3" style="display: none;">
    <h2>Review and Submit</h2>
    
    <div id="form-summary">
      <!-- Will be filled with JavaScript -->
    </div>
    
    <button type="button" onclick="nextStep(3, 2)">Previous</button>
    <button type="submit">Submit</button>
  </div>
</form>

<script>
  function nextStep(currentStep, nextStep) {
    // Validate current step if moving forward
    if (nextStep > currentStep) {
      const currentStepElement = document.getElementById(`step${currentStep}`);
      const inputs = currentStepElement.querySelectorAll('input[required]');
      let isValid = true;
      
      inputs.forEach(input => {
        if (!input.value) {
          isValid = false;
          input.classList.add('error');
        } else {
          input.classList.remove('error');
        }
      });
      
      if (!isValid) return;
    }
    
    // Hide current step and show next step
    document.getElementById(`step${currentStep}`).style.display = 'none';
    document.getElementById(`step${nextStep}`).style.display = 'block';
    
    // If moving to review step, populate summary
    if (nextStep === 3) {
      const formData = new FormData(document.getElementById('multi-step-form'));
      let summary = '<dl>';
      
      for (const [key, value] of formData.entries()) {
        if (value) {
          const label = document.querySelector(`label[for="${key}"]`)?.textContent || key;
          summary += `<dt>${label}</dt><dd>${value}</dd>`;
        }
      }
      
      summary += '</dl>';
      document.getElementById('form-summary').innerHTML = summary;
    }
  }
  
  document.getElementById('multi-step-form').addEventListener('submit', function(event) {
    event.preventDefault();
    // Submit form data via AJAX or other method
    alert('Form submitted successfully!');
  });
</script>
```

## Conclusion

HTML forms are a crucial part of web development, enabling user interaction and data collection. By understanding the various form elements, attributes, and best practices, you can create forms that are user-friendly, accessible, and secure.

Remember that forms should be designed with the user in mind, making them as simple and intuitive as possible while still collecting the necessary information. Always validate form data on both the client and server sides, and ensure your forms are accessible to all users, including those with disabilities.
