Codectionary / Developer documentation / HTML

HTML Forms

HTML forms are used to collect user input and send it to a server for processing. They contain interactive controls like text fields, checkboxes, radio buttons, and submit buttons. Forms are a fundamental part of web interactivity, enabling everything from login pages and search bars to complex data entry interfaces.

Before you start: HTML

Syntax

<form action="/submit" method="POST">
  <label for="field">Label:</label>
  <input type="text" id="field" name="field">
  <button type="submit">Submit</button>
</form>

Breaking down the syntax

action
The URL that receives a submission.
method
GET puts values in the URL; POST sends them in the request body.
name
Identifies a successful control in submitted form data.
for / id
Connect a visible label to its control.

How it works

A form groups controls into named values that can be sent together. Labels tell people what to enter; name attributes tell the receiving application what each value means.

Label

The user understands the requested value.

Input

The browser collects values and can check constraints.

Submit

The receiving server must validate the submitted data again.

Examples

A labelled input

Try submitting an empty or malformed address. The documentation preview blocks navigation and submission.

<form>
  <label for="email">Email address</label>
  <input id="email" name="email" type="email" required>
  <button type="submit">Check email</button>
</form>
  1. for matches id, giving the input an accessible name.
  2. name supplies the field key when a real form is submitted.
  3. required and type provide browser validation.

Basic Contact Form

A simple contact form with name, email, and message fields.

<form action="/contact" method="POST">
  <div>
    <label for="name">Full Name:</label>
    <input type="text" id="name" name="name" placeholder="John Doe" required>
  </div>
  <div>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" placeholder="john@example.com" required>
  </div>
  <div>
    <label for="message">Message:</label>
    <textarea id="message" name="message" rows="5" placeholder="Your message..."></textarea>
  </div>
  <button type="submit">Send Message</button>
</form>

Login Form

A login form with username, password, and remember me checkbox.

<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>
  <a href="/forgot-password">Forgot password?</a>
</form>

Multi-Step Registration Form

A comprehensive registration form with fieldsets grouping related inputs.

<form action="/register" method="POST">
  <fieldset>
    <legend>Personal Info</legend>
    <label for="fname">First Name:</label>
    <input type="text" id="fname" name="fname" required>
    <label for="lname">Last Name:</label>
    <input type="text" id="lname" name="lname" required>
    <label for="dob">Date of Birth:</label>
    <input type="date" id="dob" name="dob" required>
  </fieldset>
  <fieldset>
    <legend>Account Details</legend>
    <label for="reg-email">Email:</label>
    <input type="email" id="reg-email" name="email" required>
    <label for="reg-pass">Password:</label>
    <input type="password" id="reg-pass" name="password" minlength="8" required>
    <label for="confirm-pass">Confirm Password:</label>
    <input type="password" id="confirm-pass" name="confirm_password" required>
  </fieldset>
  <button type="submit">Create Account</button>
</form>

Best practices

  • Always associate labels with inputs using matching for and id attributes
  • Use the appropriate input type (email, tel, date) to trigger correct mobile keyboards
  • Include the required attribute on mandatory fields and validate both client and server side
  • Group related form controls with fieldset and legend elements
  • Use autocomplete attributes to help browsers autofill common fields
  • Provide clear error messages and visual feedback when validation fails

Browser compatibility

Support applies to the named feature, not every attribute or behaviour in this article. Versions refer to browsers, not operating systems.

<form>

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
From 3
Edge
Supported
From 12
Opera
Supported
From 15

Mobile

Safari on iOS
Supported
From 2
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1

Safari

  • From 3

Edge

  • From 12

Opera

  • From 15

Safari on iOS

  • From 2

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<form> action

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
From 3
Edge
Supported
From 12
Opera
Supported
From 15

Mobile

Safari on iOS
Supported
From 2
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1

Safari

  • From 3

Edge

  • From 12

Opera

  • From 15

Safari on iOS

  • From 2

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<form> method

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
From 3
Edge
Supported
From 12
Opera
Supported
From 15

Mobile

Safari on iOS
Supported
From 2
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1

Safari

  • From 3

Edge

  • From 12

Opera

  • From 15

Safari on iOS

  • From 2

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<form> enctype

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
From 3
Edge
Supported
From 12
Opera
Supported
From 15

Mobile

Safari on iOS
Supported
From 2
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1

Safari

  • From 3

Edge

  • From 12

Opera

  • From 15

Safari on iOS

  • From 2

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<form> novalidate

Desktop

Chrome
Supported
From 10
Firefox
Supported
From 4
Safari
Supported
From 10.1
Edge
Supported
From 12
Opera
Supported
From 15

Mobile

Safari on iOS
Supported
From 10.3
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature

Support history and limitations

Chrome

  • From 10

Firefox

  • From 4

Safari

  • From 10.1

Edge

  • From 12

Opera

  • From 15

Safari on iOS

  • From 10.3

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<input>

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
From 1
Edge
Supported
From 12
Opera
Supported
By 12.1 (possibly earlier)

Mobile

Safari on iOS
Supported
From 1
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1 · Before Firefox 89, manipulating the content of <input> elements using Document.execCommand() commands requires workarounds (see bug 1220696).

Safari

  • From 1

Edge

  • From 12

Opera

  • By 12.1 (possibly earlier)

Safari on iOS

  • From 1

Chrome for Android

  • From 18

Firefox for Android

  • From 4 · Before Firefox for Android 89, manipulating the content of <input> elements using Document.execCommand() commands requires workarounds (see bug 1220696).

Samsung Internet

  • From 1.0
<button>

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
From 1
Edge
Supported
From 12
Opera
Supported
By 15 (possibly earlier)

Mobile

Safari on iOS
Supported
From 1
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1

Safari

  • From 1

Edge

  • From 12

Opera

  • By 15 (possibly earlier)

Safari on iOS

  • From 1

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<label>

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
By 4 (possibly earlier)
Edge
Supported
From 12
Opera
Supported
From 15

Mobile

Safari on iOS
Supported
By 3.2 (possibly earlier)
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1

Safari

  • By 4 (possibly earlier)

Edge

  • From 12

Opera

  • From 15

Safari on iOS

  • By 3.2 (possibly earlier)

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<textarea>

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
By 4 (possibly earlier)
Edge
Supported
From 12
Opera
Supported
By 12.1 (possibly earlier)

Mobile

Safari on iOS
Supported
By 3 (possibly earlier)
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1 · Before Firefox 6, when a <textarea> was focused, the insertion point was placed at the end of the text by default. Other major browsers place the insertion point at the beginning of the text. · A default background-image gradient is applied to all <textarea> elements, which can be disabled using background-image: none. · Before Firefox 89, manipulating the content of <textarea> elements using Document.execCommand() commands requires workarounds (see bug 1220696).

Safari

  • By 4 (possibly earlier)

Edge

  • From 12

Opera

  • By 12.1 (possibly earlier)

Safari on iOS

  • By 3 (possibly earlier) · Unlike other major browsers, a default style of opacity: 0.4 is applied to disabled <textarea> elements.

Chrome for Android

  • From 18

Firefox for Android

  • From 4 · Before Firefox for Android 6, when a <textarea> was focused, the insertion point was placed at the end of the text by default. Other major browsers place the insertion point at the beginning of the text. · A default background-image gradient is applied to all <textarea> elements, which can be disabled using background-image: none. · Before Firefox for Android 89, manipulating the content of <textarea> elements using Document.execCommand() commands requires workarounds (see bug 1220696).

Samsung Internet

  • From 1.0
<select>

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
From 1
Edge
Supported
From 12
Opera
Supported
From 2

Mobile

Safari on iOS
Supported
From 1
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 1 · border-radius on <select> elements is ignored unless -webkit-appearance is overridden to an appropriate value.

Firefox

  • From 1 · Historically, Firefox has allowed keyboard and mouse events to bubble up from the <option> element to the parent <select> element, although this behavior is inconsistent across many browsers. For better Web compatibility (and for technical reasons), when Firefox is in multi-process mode the <select> element is displayed as a drop-down list. The behavior is unchanged if the <select> is presented inline and it has either the multiple attribute defined or a size attribute set to more than 1. Rather than watching <option> elements for events, you should watch for change events on <select>. See bug 1090602 for details.

Safari

  • From 1 · border-radius on <select> elements is ignored unless -webkit-appearance is overridden to an appropriate value.

Edge

  • From 12

Opera

  • From 2

Safari on iOS

  • From 1 · border-radius on <select> elements is ignored unless -webkit-appearance is overridden to an appropriate value.

Chrome for Android

  • From 18 · border-radius on <select> elements is ignored unless -webkit-appearance is overridden to an appropriate value.

Firefox for Android

  • From 4 · Firefox for Android, by default, sets a background-image gradient on all <select multiple> elements. This can be disabled using background-image: none.

Samsung Internet

  • From 1.0 · border-radius on <select> elements is ignored unless -webkit-appearance is overridden to an appropriate value.
<fieldset>

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
By 4 (possibly earlier)
Edge
Supported
From 12
Opera
Supported
By 15 (possibly earlier)

Mobile

Safari on iOS
Supported
By 3.2 (possibly earlier)
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 1 · Before version 86, this element did not support flexbox and grid layouts within this element. See bug 41027853.

Firefox

  • From 1

Safari

  • By 4 (possibly earlier)

Edge

  • From 12 · Before version 86, this element did not support flexbox and grid layouts within this element. See bug 4511145.

Opera

  • By 15 (possibly earlier)

Safari on iOS

  • By 3.2 (possibly earlier)

Chrome for Android

  • From 18 · Before version 86, this element did not support flexbox and grid layouts within this element. See bug 41027853.

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0 · Before version 14.0, this element did not support flexbox and grid layouts within this element. See bug 41027853.
<legend>

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
From 3
Edge
Supported
From 12
Opera
Supported
By 12.1 (possibly earlier)

Mobile

Safari on iOS
Supported
From 1
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1

Safari

  • From 3

Edge

  • From 12

Opera

  • By 12.1 (possibly earlier)

Safari on iOS

  • From 1

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<input> type="text"

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
From 1
Edge
Supported
From 12
Opera
Supported
From 15

Mobile

Safari on iOS
Supported
From 1
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1

Safari

  • From 1

Edge

  • From 12

Opera

  • From 15

Safari on iOS

  • From 1

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<input> type="email"

Desktop

Chrome
Supported
From 5
Firefox
Supported
From 1
Safari
Supported
From 5
Edge
Supported
From 12
Opera
Supported
From 11

Mobile

Safari on iOS
Supported
From 3
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 5

Firefox

  • From 1

Safari

  • From 5

Edge

  • From 12

Opera

  • From 11

Safari on iOS

  • From 3 · Doesn't do validation, but instead offers a custom 'email' keyboard, which is designed to make entering email addresses easier. · The custom 'email' keyboard does not provide a comma key, so users cannot enter multiple email addresses. · Automatically applies a default style of opacity: 0.4 to disable textual <input> elements, including those of type 'email'. Other major browsers don't currently share this particular default style.

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<input> type="password"

Desktop

Chrome
Supported
From 1
Firefox
Supported
From 1
Safari
Supported
From 1
Edge
Supported
From 12
Opera
Supported
From 2

Mobile

Safari on iOS
Supported
From 1
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 1

Firefox

  • From 1

Safari

  • From 1

Edge

  • From 12

Opera

  • From 2

Safari on iOS

  • From 1

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<input> required

Desktop

Chrome
Supported
From 4
Firefox
Supported
From 4
Safari
Supported
From 5
Edge
Supported
From 12
Opera
Supported
By 12.1 (possibly earlier)

Mobile

Safari on iOS
Supported
From 4
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 4

Firefox

  • From 4

Safari

  • From 5

Edge

  • From 12

Opera

  • By 12.1 (possibly earlier)

Safari on iOS

  • From 4

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0
<input> minlength

Desktop

Chrome
Supported
From 40
Firefox
Supported
From 51
Safari
Supported
From 10.1
Edge
Supported
From 17
Opera
Supported
From 27

Mobile

Safari on iOS
Supported
From 10.3
Chrome for Android
Supported
From 40
Firefox for Android
Supported
From 51
Samsung Internet
Supported
From 4.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 40

Firefox

  • From 51

Safari

  • From 10.1

Edge

  • From 17

Opera

  • From 27

Safari on iOS

  • From 10.3

Chrome for Android

  • From 40

Firefox for Android

  • From 51

Samsung Internet

  • From 4.0
HTMLFormElement.checkValidity

Desktop

Chrome
Supported
From 4
Firefox
Supported
From 4
Safari
Supported
From 5
Edge
Supported
From 12
Opera
Supported
By 12.1 (possibly earlier)

Mobile

Safari on iOS
Supported
From 4
Chrome for Android
Supported
From 18
Firefox for Android
Supported
From 4
Samsung Internet
Supported
From 1.0

MDN BCD record for this feature · MDN reference

Support history and limitations

Chrome

  • From 4

Firefox

  • From 4

Safari

  • From 5

Edge

  • From 12

Opera

  • By 12.1 (possibly earlier)

Safari on iOS

  • From 4

Chrome for Android

  • From 18

Firefox for Android

  • From 4

Samsung Internet

  • From 1.0

MDN BCD 8.1.5 · Dataset built 2026-10-08 · Mapping reviewed 2026-10-21. These dates are not individual browser-test or claim-verification dates. Unknown means the data does not establish support.

HTML Living Standard

When should I use this?

Use a form to collect and submit input, including searches, preferences and sign-in details.

Common mistakes

An input without a name

An id helps connect the label, but does not name the submitted value.

Incorrect

<input id="email" type="email">

Corrected

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

Compare approaches

  • GET: Read-only searches and URLs users can bookmark.
  • POST: Submitting changes or data that should not be placed in a URL. HTTPS is still needed.

Accessibility

  • Keep visible labels; placeholders are hints, not replacements.
  • Explain errors in text and connect them to the relevant controls.
  • Group related choices with fieldset and legend.

Explore deeper

Browser checks are a convenience

required and type="email" help users catch mistakes but can be bypassed. Validate input and permissions on the server. Never put passwords in a GET query.

Specifications & further reading