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:
custname
custtel
custemail
size
small
, medium
, or large
toppings
bacon
, cheese
, onion
, and mushroom
delivery
comments
This 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-charset
action
autocomplete
enctype
method
name
novalidate
target
[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.
elements
Returns an HTMLCollection
of the form controls in
the form (excluding image buttons for historical reasons).
length
Returns 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.disabled
form
name
interface 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.
type
Returns the string "fieldset".
elements
Returns 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
fieldset
s, 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 fieldset
s 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.
form
Returns 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.form
for
interface 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.
control
Returns 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.
labels
Returns 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>