This is a work in progress! For the latest updates from the HTML WG, possibly including important bug fixes, please look at the editor's draft instead. There may also be a more up-to-date Working Draft with changes based on resolution of Last Call issues.
This section is non-normative.
A form is a component of a Web page that has form controls, such as text fields, buttons, checkboxes, range controls, or color pickers. A user can interact with such a form, providing data that can then be sent to the server for further processing (e.g. returning the results of a search or calculation). No client-side scripting is needed in many cases, though an API is available so that scripts can augment the user experience or use forms for purposes other than submitting data to a server.
Writing a form consists of several steps, which can be performed in any order: writing the user interface, implementing the server-side processing, and configuring the user interface to communicate with the server.
This section is non-normative.
For the purposes of this brief introduction, we will create a pizza ordering form.
Any form starts with a form element, inside which
  are placed the controls. Most controls are represented by the
  input element, which by default provides a one-line
  text field. To label a control, the label element is
  used; the label text and the control itself go inside the
  label element. Each part of a form is considered a
  paragraph, and is typically separated from other parts
  using p elements. Putting this together, here is how
  one might ask for the customer's name:
<form> <p><label>Customer name: <input></label></p> </form>
To let the user select the size of the pizza, we can use a set of
  radio buttons. Radio buttons also use the input
  element, this time with a type
  attribute with the value radio. To make the radio
  buttons work as a group, they are given a common name using the
  name attribute. To group a batch
  of controls together, such as, in this case, the radio buttons, one
  can use the fieldset element. The title of such a group
  of controls is given by the first element in the
  fieldset, which has to be a legend
  element.
<form> <p><label>Customer name: <input></label></p> <fieldset> <legend> Pizza Size </legend> <p><label> <input type=radio name=size> Small </label></p> <p><label> <input type=radio name=size> Medium </label></p> <p><label> <input type=radio name=size> Large </label></p> </fieldset> </form>
Changes from the previous step are highlighted.
To pick toppings, we can use checkboxes. These use the
  input element with a type attribute with the value checkbox:
<form> <p><label>Customer name: <input></label></p> <fieldset> <legend> Pizza Size </legend> <p><label> <input type=radio name=size> Small </label></p> <p><label> <input type=radio name=size> Medium </label></p> <p><label> <input type=radio name=size> Large </label></p> </fieldset> <fieldset> <legend> Pizza Toppings </legend> <p><label> <input type=checkbox> Bacon </label></p> <p><label> <input type=checkbox> Extra Cheese </label></p> <p><label> <input type=checkbox> Onion </label></p> <p><label> <input type=checkbox> Mushroom </label></p> </fieldset> </form>
The pizzeria for which this form is being written is always
  making mistakes, so it needs a way to contact the customer. For this
  purpose, we can use form controls specifically for telephone numbers
  (input elements with their type attribute set to tel) and e-mail addresses
  (input elements with their type attribute set to email):
<form> <p><label>Customer name: <input></label></p> <p><label>Telephone: <input type=tel></label></p> <p><label>E-mail address: <input type=email></label></p> <fieldset> <legend> Pizza Size </legend> <p><label> <input type=radio name=size> Small </label></p> <p><label> <input type=radio name=size> Medium </label></p> <p><label> <input type=radio name=size> Large </label></p> </fieldset> <fieldset> <legend> Pizza Toppings </legend> <p><label> <input type=checkbox> Bacon </label></p> <p><label> <input type=checkbox> Extra Cheese </label></p> <p><label> <input type=checkbox> Onion </label></p> <p><label> <input type=checkbox> Mushroom </label></p> </fieldset> </form>
We can use an input element with its type attribute set to time to ask for a delivery
  time. Many of these form controls have attributes to control exactly
  what values can be specified; in this case, three attributes of
  particular interest are min,
  max, and step. These set the minimum time, the
  maximum time, and the interval between allowed values (in
  seconds). This pizzeria only delivers between 11am and 9pm, and
  doesn't promise anything better than 15 minute increments, which we
  can mark up as follows:
<form> <p><label>Customer name: <input></label></p> <p><label>Telephone: <input type=tel></label></p> <p><label>E-mail address: <input type=email></label></p> <fieldset> <legend> Pizza Size </legend> <p><label> <input type=radio name=size> Small </label></p> <p><label> <input type=radio name=size> Medium </label></p> <p><label> <input type=radio name=size> Large </label></p> </fieldset> <fieldset> <legend> Pizza Toppings </legend> <p><label> <input type=checkbox> Bacon </label></p> <p><label> <input type=checkbox> Extra Cheese </label></p> <p><label> <input type=checkbox> Onion </label></p> <p><label> <input type=checkbox> Mushroom </label></p> </fieldset> <p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900"></label></p> </form>
The textarea element can be used to provide a
  free-form text field. In this instance, we are going to use it to
  provide a space for the customer to give delivery instructions:
<form> <p><label>Customer name: <input></label></p> <p><label>Telephone: <input type=tel></label></p> <p><label>E-mail address: <input type=email></label></p> <fieldset> <legend> Pizza Size </legend> <p><label> <input type=radio name=size> Small </label></p> <p><label> <input type=radio name=size> Medium </label></p> <p><label> <input type=radio name=size> Large </label></p> </fieldset> <fieldset> <legend> Pizza Toppings </legend> <p><label> <input type=checkbox> Bacon </label></p> <p><label> <input type=checkbox> Extra Cheese </label></p> <p><label> <input type=checkbox> Onion </label></p> <p><label> <input type=checkbox> Mushroom </label></p> </fieldset> <p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900"></label></p> <p><label>Delivery instructions: <textarea></textarea></label></p> </form>
Finally, to make the form submittable we use the
  button element:
<form> <p><label>Customer name: <input></label></p> <p><label>Telephone: <input type=tel></label></p> <p><label>E-mail address: <input type=email></label></p> <fieldset> <legend> Pizza Size </legend> <p><label> <input type=radio name=size> Small </label></p> <p><label> <input type=radio name=size> Medium </label></p> <p><label> <input type=radio name=size> Large </label></p> </fieldset> <fieldset> <legend> Pizza Toppings </legend> <p><label> <input type=checkbox> Bacon </label></p> <p><label> <input type=checkbox> Extra Cheese </label></p> <p><label> <input type=checkbox> Onion </label></p> <p><label> <input type=checkbox> Mushroom </label></p> </fieldset> <p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900"></label></p> <p><label>Delivery instructions: <textarea></textarea></label></p> <p><button>Submit order</button></p> </form>
This section is non-normative.
The exact details for writing a server-side processor are out of
  scope for this specification. For the purposes of this introduction,
  we will assume that the script at https://pizza.example.com/order.cgi is configured to
  accept submissions using the application/x-www-form-urlencoded
  format, expecting the following parameters sent in an HTTP POST
  body:
custnamecusttelcustemailsizesmall, medium, or largetoppingsbacon, cheese, onion, and mushroomdeliverycommentsThis section is non-normative.
Form submissions are exposed to servers in a variety of ways,
  most commonly as HTTP GET or POST requests. To specify the exact
  method used, the method
  attribute is specified on the form element. This
  doesn't specify how the form data is encoded, though; to specify
  that, you use the enctype
  attribute. You also have to specify the URL of the
  service that will handle the submitted data, using the action attribute.
For each form control you want submitted, you then have to give a
  name that will be used to refer to the data in the submission. We
  already specified the name for the group of radio buttons; the same
  attribute (name) also specifies
  the submission name. Radio buttons can be distinguished from each
  other in the submission by giving them different values, using the
  value attribute.
Multiple controls can have the same name; for example, here we
  give all the checkboxes the same name, and the server distinguishes
  which checkbox was checked by seeing which values are submitted with
  that name — like the radio buttons, they are also given unique
  values with the value
  attribute.
Given the settings in the previous section, this all becomes:
<form method="post"
      enctype="application/x-www-form-urlencoded"
      action="https://pizza.example.com/order.cgi">
 <p><label>Customer name: <input name="custname"></label></p>
 <p><label>Telephone: <input type=tel name="custtel"></label></p>
 <p><label>E-mail address: <input type=email name="custemail"></label></p>
 <fieldset>
  <legend> Pizza Size </legend>
  <p><label> <input type=radio name=size value="small"> Small </label></p>
  <p><label> <input type=radio name=size value="medium"> Medium </label></p>
  <p><label> <input type=radio name=size value="large"> Large </label></p>
 </fieldset>
 <fieldset>
  <legend> Pizza Toppings </legend>
  <p><label> <input type=checkbox name="topping" value="bacon"> Bacon </label></p>
  <p><label> <input type=checkbox name="topping" value="cheese"> Extra Cheese </label></p>
  <p><label> <input type=checkbox name="topping" value="onion"> Onion </label></p>
  <p><label> <input type=checkbox name="topping" value="mushroom"> Mushroom </label></p>
 </fieldset>
 <p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900" name="delivery"></label></p>
 <p><label>Delivery instructions: <textarea name="comments"></textarea></label></p>
 <p><button>Submit order</button><p>
</form>For example, if the customer entered "Denise Lawrence" as their name, "555-321-8642" as their telephone number, did not specify an e-mail address, asked for a medium-sized pizza, selected the Extra Cheese and Mushroom toppings, entered a delivery time of 7pm, and left the delivery instructions text field blank, the user agent would submit the following to the online Web service:
custname=Denise+Lawrence&custtel=555-321-8624&custemail=&size=medium&topping=cheese&topping=mushroom&delivery=19%3A00&comments=
This section is non-normative.
Forms can be annotated in such a way that the user agent will check the user's input before the form is submitted. The server still has to verify the input is valid (since hostile users can easily bypass the form validation), but it allows the user to avoid the wait incurred by having the server be the sole checker of the user's input.
The simplest annotation is the required attribute, which can be
  specified on input elements to indicate that the form
  is not to be submitted until a value is given. By adding this
  attribute to the customer name and delivery time fields, we allow
  the user agent to notify the user when the user submits the form
  without filling in those fields:
<form method="post"
      enctype="application/x-www-form-urlencoded"
      action="https://pizza.example.com/order.cgi">
 <p><label>Customer name: <input name="custname" required></label></p>
 <p><label>Telephone: <input type=tel name="custtel"></label></p>
 <p><label>E-mail address: <input type=email name="custemail"></label></p>
 <fieldset>
  <legend> Pizza Size </legend>
  <p><label> <input type=radio name=size value="small"> Small </label></p>
  <p><label> <input type=radio name=size value="medium"> Medium </label></p>
  <p><label> <input type=radio name=size value="large"> Large </label></p>
 </fieldset>
 <fieldset>
  <legend> Pizza Toppings </legend>
  <p><label> <input type=checkbox name="topping" value="bacon"> Bacon </label></p>
  <p><label> <input type=checkbox name="topping" value="cheese"> Extra Cheese </label></p>
  <p><label> <input type=checkbox name="topping" value="onion"> Onion </label></p>
  <p><label> <input type=checkbox name="topping" value="mushroom"> Mushroom </label></p>
 </fieldset>
 <p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900" name="delivery" required></label></p>
 <p><label>Delivery instructions: <textarea name="comments"></textarea></label></p>
 <p><button>Submit order</button><p>
</form>It is also possible to limit the length of the input, using the
  maxlength attribute. By
  adding this to the textarea element, we can limit users
  to 1000 characters, preventing them from writing huge essays to the
  busy delivery drivers instead of staying focused and to the
  point:
<form method="post"
      enctype="application/x-www-form-urlencoded"
      action="https://pizza.example.com/order.cgi">
 <p><label>Customer name: <input name="custname" required></label></p>
 <p><label>Telephone: <input type=tel name="custtel"></label></p>
 <p><label>E-mail address: <input type=email name="custemail"></label></p>
 <fieldset>
  <legend> Pizza Size </legend>
  <p><label> <input type=radio name=size value="small"> Small </label></p>
  <p><label> <input type=radio name=size value="medium"> Medium </label></p>
  <p><label> <input type=radio name=size value="large"> Large </label></p>
 </fieldset>
 <fieldset>
  <legend> Pizza Toppings </legend>
  <p><label> <input type=checkbox name="topping" value="bacon"> Bacon </label></p>
  <p><label> <input type=checkbox name="topping" value="cheese"> Extra Cheese </label></p>
  <p><label> <input type=checkbox name="topping" value="onion"> Onion </label></p>
  <p><label> <input type=checkbox name="topping" value="mushroom"> Mushroom </label></p>
 </fieldset>
 <p><label>Preferred delivery time: <input type=time min="11:00" max="21:00" step="900" name="delivery" required></label></p>
 <p><label>Delivery instructions: <textarea name="comments" maxlength=1000></textarea></label></p>
 <p><button>Submit order</button><p>
</form>Mostly for historical reasons, elements in this section fall into several overlapping (but subtly different) categories in addition to the usual ones like flow content, phrasing content, and interactive content.
A number of the elements are form-associated elements, which means they can have a
  form owner and, to expose this, have a form content attribute with a matching
  form IDL attribute.
The form-associated elements fall into several subcategories:
Denotes elements that are listed in the form.elements
    and fieldset.elements APIs.
Denotes elements that can be associated with label
    elements.
Denotes elements that can be used for constructing the form data
    set when a form element is submitted.
Denotes elements that can be affected when a form
    element is reset.
In addition, some submittable elements can be, depending on their attributes, buttons. The prose below defines when an element is a button. Some buttons are specifically submit buttons.
The object element is also a
  form-associated element and can, with the use of a
  suitable plugin, partake in form
  submission.
form elementform element descendants.accept-charsetactionautocompleteenctypemethodnamenovalidatetarget[OverrideBuiltins]
interface HTMLFormElement : HTMLElement {
           attribute DOMString acceptCharset;
           attribute DOMString action;
           attribute DOMString autocomplete;
           attribute DOMString enctype;
           attribute DOMString encoding;
           attribute DOMString method;
           attribute DOMString name;
           attribute boolean noValidate;
           attribute DOMString target;
  readonly attribute HTMLFormControlsCollection elements;
  readonly attribute long length;
  caller getter any (in unsigned long index);
  caller getter any (in DOMString name);
  void submit();
  void reset();
  boolean checkValidity();
};
   The form element represents a
  collection of form-associated
  elements, some of which can represent editable values that
  can be submitted to a server for processing.
The accept-charset
  attribute gives the character encodings that are to be used for the
  submission. If specified, the value must be an ordered set of
  unique space-separated tokens that are ASCII
  case-insensitive, and each token must be an ASCII
  case-insensitive match for the preferred MIME
  name of an ASCII-compatible character encoding.
  [IANACHARSET]
The name attribute
  represents the form's name within the forms collection. The value must
  not be the empty string, and the value must be unique amongst the
  form elements in the forms collection that it is in, if
  any.
The autocomplete
  attribute is an enumerated attribute. The attribute has
  two states. The on
  keyword maps to the on state, and the
  off keyword maps to
  the off
  state. The attribute may also be omitted. The missing value
  default is the on state. The off state indicates
  that by default, input elements in the form will have
  their resulting autocompletion state set to off; the on state indicates
  that by default, input elements in the form will have
  their resulting autocompletion state set to on.
The action, enctype, method, novalidate, and target attributes are attributes
  for form submission.
elementsReturns an HTMLCollection of the form controls in
    the form (excluding image buttons for historical reasons).
lengthReturns the number of form controls in the form (excluding image buttons for historical reasons).
Returns the indexth element in the form (excluding image buttons for historical reasons).
Returns the form control in the form with the given ID or name (excluding image buttons for
    historical reasons).
Once an element has been referenced using a particular name,
    that name will continue being available as a way to reference that
    element in this method, even if the element's actual ID or name changes, for as long as the
    element remains in the Document.
If there are multiple matching items, then a
    NodeList object containing all those elements is
    returned.
Returns null if no element with that ID or name could be found.
submit()Submits the form.
reset()Resets the form.
checkValidity()Returns true if the form's controls are all valid; otherwise, returns false.
The autocomplete IDL
  attribute must reflect the content attribute of the
  same name, limited to only known values.
The name IDL
  attribute must reflect the content attribute of the
  same name.
The acceptCharset IDL
  attribute must reflect the accept-charset content
  attribute.
The elements
  IDL attribute must return an HTMLFormControlsCollection
  rooted at the Document node, whose filter matches listed elements whose form
  owner is the form element, with the exception of
  input elements whose type attribute is in the Image Button state, which must,
  for historical reasons, be excluded from this particular
  collection.
The length IDL
  attribute must return the number of nodes represented by the elements collection.
The supported property indices at any instant are
  the indices supported by the object returned by the elements attribute at that
  instant.
When a form element is indexed for indexed property retrieval,
  the user agent must return the value returned by the item method on
  the elements collection, when
  invoked with the given index as its argument.
Each form element has a mapping of names to elements
  called the past names map. It is used to persist names of
  controls even when they change names.
The supported property names are the union of the
  names currently supported by the object returned by the elements attribute, and the names
  currently in the past names map.
When a form element is indexed for named property
  retrieval, the user agent must run the following steps:
If name is one of the supported
    property names of the object returned by the elements attribute, then run
    these substeps:
Let candidate be the object returned
     by the namedItem()
     method on the object returned by the elements attribute when passed
     the name argument.
If candidate is an element, then add a
     mapping from name to candidate in the form element's
     past names map, replacing the previous entry with
     the same name, if any.
Return candidate and abort these steps.
Otherwise, name is the name of one of
   the entries in the form element's past names
   map: return the object associated with name in that map.
If an element listed in the form element's past
  names map is removed from the Document, then its
  entries must be removed from the map.
The submit()
  method, when invoked, must submit the form
  element from the form element itself, with the scripted-submit flag set.
The reset()
  method, when invoked, must run the following steps:
If the form element is marked as locked for
   reset, then abort these steps.
Mark the form element as locked for
   reset.
Unmark the form element as locked for
   reset.
If the checkValidity()
  method is invoked, the user agent must statically validate the
  constraints of the form element, and return true
  if the constraint validation return a positive result, and
  false if it returned a negative result.
This example shows two search forms:
<form action="http://www.google.com/search" method="get"> <label>Google: <input type="search" name="q"></label> <input type="submit" value="Search..."> </form> <form action="http://www.bing.com/search" method="get"> <label>Bing: <input type="search" name="q"></label> <input type="submit" value="Search..."> </form>
fieldset elementlegend element, followed by flow content.disabledformnameinterface HTMLFieldSetElement : HTMLElement {
           attribute boolean disabled;
  readonly attribute HTMLFormElement form;
           attribute DOMString name;
  readonly attribute DOMString type;
  readonly attribute HTMLFormControlsCollection elements;
  readonly attribute boolean willValidate;
  readonly attribute ValidityState validity;
  readonly attribute DOMString validationMessage;
  boolean checkValidity();
  void setCustomValidity(in DOMString error);
};
   The fieldset element represents a set
  of form controls optionally grouped under a common name.
The name of the group is given by the first legend
  element that is a child of the fieldset element, if
  any. The remainder of the descendants form the group.
The disabled
  attribute, when specified, causes all the form control descendants
  of the fieldset element, excluding those that are
  descendants of the fieldset element's first
  legend element child, if any, to be disabled.
The form attribute is used to
  explicitly associate the fieldset element with its
  form owner. The name
  attribute represents the element's name.
typeReturns the string "fieldset".
elementsReturns an HTMLFormControlsCollection of the form
    controls in the element.
The disabled IDL
  attribute must reflect the content attribute of the
  same name.
The type IDL
  attribute must return the string "fieldset".
The elements IDL
  attribute must return an HTMLFormControlsCollection
  rooted at the fieldset element, whose filter matches
  listed elements.
The willValidate, validity, and validationMessage
  attributes, and the checkValidity() and setCustomValidity()
  methods, are part of the constraint validation API. The
  form and name IDL attributes are part of the
  element's forms API.
Constraint validation: fieldset
  elements are always barred from constraint
  validation.
The following snippet shows a fieldset with a checkbox in the legend that controls whether or not the fieldset is enabled. The contents of the fieldset consist of two required text fields and an optional year/month control.
<fieldset name="clubfields" disabled> <legend> <label> <input type=checkbox name=club onchange="form.clubfields.disabled = !checked"> Use Club Card </label> </legend> <p><label>Name on card: <input name=clubname required></label></p> <p><label>Card number: <input name=clubnum required pattern="[-0-9]+"></label></p> <p><label>Expiry date: <input name=clubexp type=month></label></p> </fieldset>
You can also nest fieldset elements. Here is an
   example expanding on the previous one that does so:
<fieldset name="clubfields" disabled> <legend> <label> <input type=checkbox name=club onchange="form.clubfields.disabled = !checked"> Use Club Card </label> </legend> <p><label>Name on card: <input name=clubname required></label></p> <fieldset name="numfields"> <legend> <label> <input type=radio checked name=clubtype onchange="form.numfields.disabled = !checked"> My card has numbers on it </label> </legend> <p><label>Card number: <input name=clubnum required pattern="[-0-9]+"></label></p> </fieldset> <fieldset name="letfields" disabled> <legend> <label> <input type=radio name=clubtype onchange="form.letfields.disabled = !checked"> My card has letters on it </label> </legend> <p><label>Card code: <input name=clublet required pattern="[A-Za-z]+"></label></p> </fieldset> </fieldset>
In this example, if the outer "Use Club Card" checkbox is not
   checked, everything inside the outer fieldset,
   including the two radio buttons in the legends of the two nested
   fieldsets, will be disabled. However, if the checkbox
   is checked, then the radio buttons will both be enabled and will
   let you select which of the two inner fieldsets is to
   be enabled.
legend elementfieldset element.interface HTMLLegendElement : HTMLElement {
  readonly attribute HTMLFormElement form;
};
   The legend element represents a caption
  for the rest of the contents of the legend element's
  parent fieldset element, if
  any.
formReturns the element's form element, if any, or
    null otherwise.
The form IDL
  attribute's behavior depends on whether the legend
  element is in a fieldset element or not. If the
  legend has a fieldset element as its
  parent, then the form IDL
  attribute must return the same value as the form IDL attribute on that
  fieldset element. Otherwise, it must return null.
label elementlabel elements.formforinterface HTMLLabelElement : HTMLElement {
  readonly attribute HTMLFormElement form;
           attribute DOMString htmlFor;
  readonly attribute HTMLElement control;
};
   The label represents a caption in a
  user interface. The caption can be associated with a specific form
  control, known as the label
  element's labeled control, either using for attribute, or by putting the form
  control inside the label element itself.
Except where otherwise specified by the following rules, a
  label element has no labeled control.
The for attribute
  may be specified to indicate a form control with which the caption
  is to be associated. If the attribute is specified, the attribute's
  value must be the ID of a labelable
  form-associated element in the same Document as
  the label element. If the attribute
  is specified and there is an element in the Document
  whose ID is equal to the value of the for attribute, and the first such
  element is a labelable form-associated
  element, then that element is the label
  element's labeled control.
If the for attribute is not
  specified, but the label element has a labelable form-associated element
  descendant, then the first such descendant in tree
  order is the label element's labeled
  control.
The label element's exact default presentation and
  behavior, in particular what its activation behavior
  might be, if anything, should match the platform's label
  behavior.
For example, on platforms where clicking a checkbox label checks
   the checkbox, clicking the label in the following
   snippet could trigger the user agent to run synthetic click
   activation steps on the input element, as if
   the element itself had been triggered by the user:
<label><input type=checkbox name=lost> Lost</label>
On other platforms, the behavior might be just to focus the control, or do nothing.
controlReturns the form control that is associated with this element.
The form attribute is used to
  explicitly associate the label element with its
  form owner.
The htmlFor IDL
  attribute must reflect the for content attribute.
The control IDL
  attribute must return the label element's labeled
  control, if any, or null if there isn't one.
labelsReturns a NodeList of all the label
    elements that the form control is associated with.
Labelable form-associated
  elements have a NodeList object associated with
  them that represents the list of label elements, in
  tree order, whose labeled control is the
  element in question. The labels IDL attribute of
  labelable form-associated
  elements, on getting, must return that NodeList
  object.
The form IDL attribute is part
  of the element's forms API.
The following example shows three form controls each with a label, two of which have small text showing the right format for users to use.
<p><label>Full name: <input name=fn> <small>Format: First Last</small></label></p> <p><label>Age: <input name=age type=number min=0></label></p> <p><label>Post code: <input name=pc> <small>Format: AB12 3CD</small></label></p>