• Organism
  • CORE COMPONENT
  • Taxonomic name: O-FORM
  • Added on: v3.0.0 (15/09/17)
  • Updated on: v5.10.0 (10/08/21)

Forms introduction

This page explains the basics of how to set up forms within your pages. The design tab contains visual representations and shows how forms should be structured, while the code tab contains details for developers on the correct markup structures required and the different elements that can be contained within them.


Design and usage

Structure

  • Standard form controls

    • Standard form controls fields can display either as max of 6 columns or to the max width of the content they contain. For example, a payment card security code text field would be the width of 3 or 4 characters.
    • The label is placed 15px above the text field.
  • Radio and radio - segmented controls

    • Radio - segmented controls can display a maximum of 3 controls and are 6 columns in width by default.
    • Radio buttons are 6 columns in width by default, but can expand to 8 columns in the case of long labels at a designer's discretion; this rule applies to both standard and double-column variants.
    • Radio - segmented controls can expand to 8 columns if the content inside them wraps on more than two lines; text is prohibited to wrap to a third line. On tablet, this will wrap to three lines or back to two lines on mobile.
  • Notification cards

    • Notification cards are a maximum of 8 columns wide.
  • Full-page modals

    • Full page modals follows the same rules as standard forms.

Labels

  • Standard form controls, radio and radio - segmented controls

    • The label is placed 15px above the control.
  • Full-page modals

    • Full page modals follows the same rules as standard forms.

Placement

  • Form UI elements are left aligned and placed 30px below each other.

Errors

  • Inline text errors should sit below the text field label and above the text field, with a maximum width that matches the width of the form UI element.

Accessibility and screen readers

  • Radio - segmented controls change to radio buttons when JavaScript is disabled; other standard form controls and notification cards will remain the same visually regardless of whether JavaScript is running or not.
  • Aria-invalid must be used to indicate when an error has occurred with the fieldset/form field(s).
  • Aria-describedby must be used to link any help, instructional and/or error text with the fieldset/form field(s).

Use case and exception scenarios

  • Wherever a user journey requires form UI.

Interactive examples

Static examples at all breakpoints are shown below, and a working example can be seen on the form structure page. Further working examples (without visible structures) can be seen on the form example page and the single page form example page.

Download form rules design guidance PDF
Form rules examples

Code examples

For an example layout, visit the form example page in the templates section.

Development and test

Notes for developers

When marking up a form, the following convention should be used.

<form action="..." method="...">
...
</form>

If the native form validation needs to be disabled, set the novalidate attribute on the form.

Sections

Form pages can be set up using section classes to ensure the correct spacings within and between sections; within each section, form controls should be set up within form rows within fieldsets (see below).

The different section variants allow for spacing control to match our style guide; variants exist for --in-out (padding at the top and bottom of the section), --in (top padding only), --out (bottom padding only) and --none (no padding top or bottom). The first element within these sections should carry the u-margin--top-none and the last item u-margin--bottom-none to ensure the correct spacing is determined within the sections.

Fieldsets

Forms should be logically divided up into groupings of elements (controls); typically this is done with the fieldset element.

Fieldsets should be used to contain groupings of controls which sit under a single heading (for example, name, address, telephone number and email within a Driver Deatils section), and also to contain several similar elements acting as a group (for example, a set of checkboxes, radio buttons or textboxes used to input a date)

Fieldsets should contain a legend to define the section contents, although this will not be visible by default. Use span class="a-label" to have them appear in the same style as single-element labels.

Check the documentation for each form element to determine whether it should be marked up as a fieldset with a legend or not.

Input types

Care should be taken when choosing input field types for various uses, particularly with regard to number entry, as making the wrong selection could prevent users from inputting the required details into a form. Basic details are listed below, and further information can be found on the MDN web docs site page.

<input type="number">
  • Does not stop entry beyond a maximum number (just highlights as invalid)
  • Does not support leading zeros (stripped off by some browsers, so unsuitable for telephone number, CVV or two-digit day/month entries)
  • Does not support spaces (cannot be used for visually formatting credit cards, telephone numbers, etc)
  • Numeric keyboard implementations vary and many do not correctly implement the specification's requirements for negative numbers and decimal points.
<input type="tel">

Should ONLY be used for telephone numbers; using this incorrectly for other number entries may produce a visually pleasing result but will leave code open to changes in how browsers interpret/support/validate entries of this type.

<input type="text">
  • Possible to control the maximum number of characters entered into the field
  • Possible to use regex patterns to help with validation of entries
  • Cannot control which keyboard is displayed (full / abbreviated / numeric) across touch devices. Keyboard types can be suggested for a few leading-edge browsers via the inputmode attribute, however it should be used with caution and should very much be considered as a progressive enhancement rather than being relied upon.

Aria usage for errors and help text

To aid screen reader users in completing forms without error and also with understanding and fixing any errors that have occured, some additional aria attributes are now recommended to be applied across all form fields/rows.

All form row help, explanatory text, form row instructions and form row errors must have a unique id assigned to them and be appropriately linked to either the individual form input or the form row using aria-describedby. This ensures that the help text is read out immediately on focus of the form input/fieldset. When there is more that one item that requires referencing within the aria-describedby attribute the id values must be supplied in the form of a space separated list. For example if there is an error with id of 'err1' and help text with id of 'help1' the value for the aria-describedby attribute would be 'err1 help1'.

All inline form error messages should start with the hidden text 'Error: ' so that when read by out by a screen reader it is immediately clear that the text being read is an error message.

All erroring form fields (or fieldset if a group or radios/checkboxes) must have aria-invalid="true" set on them, ensuring that when a user focus' on an errored form field, the field will be announced as invalid, so the user is then aware that there in an issue that requires fixing.

When linking help or errors, or even adding aria-invalid to the markup careful consideration must be taken as to where it is most appropriate to apply the value. The following rules should be used to decide where the attribute(s) should be applied.

  • Single form field - All attributes should be applied directly to that form field
  • Group of form fields but only one in error or help text applies to only one - Apply the attribute(s) to the only field in error or where the help text applies
  • Group of form field where all in error or the help text applies to all - Apply the attribute(s) to the groups surrounding fieldset (form row)

There may situations where more than one of these rules applies to the overall form row for example a date range where the instruction text applies to both fields so should be linked to the fieldset for the date range but one of the two fields is in error so the error should be linked to just that field not to the fieldset.

Important messages

To help those using assistive technologies, make sure that success/error messages which need to be announced to users have their aria attributes updated to role="alert" and/or aria-live="assertive".

Using autocomplete

Users appreciate when websites save them time by automatically filling common fields like names, email addresses and other frequently used fields, plus it helps to reduce potential input errors, especially on virtual keyboards and small devices.

Browsers use many methods to determine which fields they can auto-populate based on previously specified data by the user, and you can give hints to the browser by providing both the name attribute and the autocomplete attribute on each input element.

You do not want user agents to autofill sensitive customer data, ie. payment card details, please use the autocomplete="off" attribute value

For example, to hint to the browser that it should auto-complete the form with the users name and phone number but not their email address, you should use:

<label for="...">Name</label>
<input type="..." id="..." name="name" autocomplete="name"><label for="...">Phone</label>
<input type="..." id="..." name="phone" autocomplete="tel"><label for="...">Email</label>
<input type="..." id="..." name="email" autocomplete="off">

The most commonly used autocomplete attributes are shown below.

The autocomplete attributes can be accompanied with a section name, such as shipping given-name or billing street-address. The browser will auto-complete different sections separately, and not as a continuous form.

Content type name attribute autocomplete attribute
Name name
fname
mname
lname
name (full name)
given-name (first name)
additional-name (middle name)
family-name (last name)
Email email email
Address address
city
region
province
state
zip
zip2
postal
country
For one address input:
street-address
For two address inputs:
address-line1
address-line2
address-level1 (state or province)
address-level2 (city)
postal-code (zip code)
country
Phone phone
mobile
country-code
area-code
exchange
suffix
ext
tel
Credit Card ccname
cardnumber
cvc
ccmonth
ccyear
exp-date
card-type
cc-name
cc-number
cc-csc
cc-exp-month
cc-exp-year
cc-exp
cc-type
Usernames username username
Passwords password current-password (for sign-in forms)
new-password (for sign-up and password-change forms)

Use either only street-address or both address-line1 and address-line2. address-level1 and address-level2 are only necessary if they're required for your address format.

autocomplete attribute values are part of the current WHATWG HTML Standard

Typical form markup

The markup for a typical form might look something like:

<form action="..." method="...">
	<div class="l-section [ Modifier ]">
		<div class="l-content-container">
			<fieldset>
				<legend>...</legend>
				<div class="m-form-row u-margin--top-none">
					<label>...</label>
					<div class="m-form-row__content">
						[ Single form control ]
					</div>
				</div>
				<div class="m-form-row">
					<label>...</label>
					<div class="m-form-row__content">
						[ Single form control ]
					</div>
				</div>
				<fieldset class="m-form-row">
					<legend class="a-label">...</label>
					<div class="m-form-row__content">
						[ Set of form controls, eg checkbox group ]
					</div>
				</fieldset>
				<div class="m-form-row u-margin--bottom-none">
					<label>...</label>
					<div class="m-form-row__content">
						[ Single form control ]
					</div>
				</div>
			</fieldset>
		</div>
	</div>
</form>

Component releases

  • Added on: v3.0.0 (15/09/17)
  • Updated on: v5.10.0 (10/08/21)

Latest update:

  • updated: Additional spacing has been added before the last button / button group on a form. The previous spacing means buttons appear to have a stronger relationship with the form elements immediately above them than all other form fields, which is misleading; this change offers a greater degree of cognitive separation from the element immediately above. The exceptions are when there is only one form input, and on login/register pages, where the spacing should be the standard 30px.

Full version history

A full history of changes and enhancements detailing all minor and major updates to the component.

View full version history

Want something new in Framework, or to chat about an issue you're having with it?

Contact the team