Styles
Forms
Allow users to enter information, search for content or perform tasks.
Contents
Fields
There are some common form fields that allow users to enter information.
- checkboxes
- Select multiple options from a defined list
- date input
- Enter a date using year, month and day fields
- file input
- Upload a file or multiple files
- radios
- Select a single option from a defined list
- textarea
- Enter multiple lines of text
- text input
- Enter a single line of text
If there are issues with information provided by a user, help them recover from validation errors.
HTML
<div class="tna-container">
<div class="tna-column tna-column--full">
<form novalidate>
<h1 class="tna-heading-xl">Create a record</h1>
<div class="tna-form-item">
<div class="tna-form-item__header">
<label class="tna-form-item__label tna-heading-m" for="record_file">
Upload the record
</label>
</div>
<div class="tna-form-item__body">
<input id="record_file" class="tna-file-input" name="record_file" type="file">
</div>
</div>
<div class="tna-form-item">
<div class="tna-form-item__header">
<label class="tna-form-item__label tna-heading-m" for="record_name">
Enter the name of the record
</label>
</div>
<div class="tna-form-item__body">
<input id="record_name" class="tna-text-input" name="record_name" value="" type="text" spellcheck="false" autocapitalize="off" autocorrect="off">
</div>
</div>
<div class="tna-fieldset tna-fieldset--small-hint">
<fieldset class="tna-fieldset__inner">
<legend class="tna-fieldset__legend">
<span class="tna-fieldset__heading tna-heading-m">
Select the record categories
</span>
</legend>
<div class="tna-fieldset__body">
<div class="tna-checkboxes" id="record_categories">
<div class="tna-checkboxes__item">
<input type="checkbox" id="record_categories-architectural" value="architectural" name="categories">
<label for="record_categories-architectural" class="tna-checkboxes__item-label">
Architectural
</label>
</div>
<div class="tna-checkboxes__item">
<input type="checkbox" id="record_categories-banking" value="banking" name="categories">
<label for="record_categories-banking" class="tna-checkboxes__item-label">
Banking
</label>
</div>
<div class="tna-checkboxes__item">
<input type="checkbox" id="record_categories-charities" value="charities" name="categories">
<label for="record_categories-charities" class="tna-checkboxes__item-label">
Charities
</label>
</div>
</div>
</div>
</fieldset>
</div>
<div class="tna-fieldset tna-fieldset--small-hint">
<fieldset class="tna-fieldset__inner">
<legend class="tna-fieldset__legend">
<span class="tna-fieldset__heading tna-heading-m">
Enter the start date of the record
</span>
</legend>
<div class="tna-fieldset__body">
<div class="tna-date-input" id="record_date">
<div class="tna-date-input__item tna-date-input__item--day">
<label for="record_date-day" class="tna-date-input__item-label">
Day
</label>
<input type="text" id="record_date-day" value="" name="date-day" class="tna-date-input__item-input" inputmode="numeric">
</div>
<div class="tna-date-input__item tna-date-input__item--month">
<label for="record_date-month" class="tna-date-input__item-label">
Month
</label>
<input type="text" id="record_date-month" value="" name="date-month" class="tna-date-input__item-input" inputmode="numeric">
</div>
<div class="tna-date-input__item tna-date-input__item--year">
<label for="record_date-year" class="tna-date-input__item-label">
Year
</label>
<input type="text" id="record_date-year" value="" name="date-year" class="tna-date-input__item-input tna-date-input__item-input--wider" inputmode="numeric">
</div>
</div>
</div>
</fieldset>
</div>
<div class="tna-fieldset tna-fieldset--small-hint">
<fieldset class="tna-fieldset__inner">
<legend class="tna-fieldset__legend">
<span class="tna-fieldset__heading tna-heading-m">
Select the type of record
</span>
</legend>
<div class="tna-fieldset__body">
<div class="tna-radios" id="record_type">
<div class="tna-radios__item">
<input type="radio" id="record_type-physical" value="physical" name="type">
<label for="record_type-physical" class="tna-radios__item-label">
Physical
</label>
</div>
<div class="tna-radios__item">
<input type="radio" id="record_type-digital" value="digital" name="type">
<label for="record_type-digital" class="tna-radios__item-label">
Digital
</label>
</div>
</div>
</div>
</fieldset>
</div>
<div class="tna-form-item">
<div class="tna-form-item__header">
<label class="tna-form-item__label tna-heading-m" for="record_feedback">
Enter the record description
</label>
</div>
<div class="tna-form-item__body">
<textarea id="record_feedback" class="tna-textarea" name="feedback" spellcheck="false" autocapitalize="off" autocorrect="off" rows="5"></textarea>
</div>
</div>
<div class="tna-button-group">
<button class="tna-button" type="submit">
Create record
</button>
</div>
</form>
</div>
</div>
Nunjucks
{% from "nationalarchives/components/button/macro.njk" import tnaButton %}
{% from "nationalarchives/components/checkboxes/macro.njk" import tnaCheckboxes %}
{% from "nationalarchives/components/date-input/macro.njk" import tnaDateInput %}
{% from "nationalarchives/components/file-input/macro.njk" import tnaFileInput %}
{% from "nationalarchives/components/radios/macro.njk" import tnaRadios %}
{% from "nationalarchives/components/textarea/macro.njk" import tnaTextarea %}
{% from "nationalarchives/components/text-input/macro.njk" import tnaTextInput %}
<div class="tna-container">
<div class="tna-column tna-column--full">
<form novalidate>
<h1 class="tna-heading-xl">Create a record</h1>
{{ tnaFileInput({
label: "Upload the record",
headingSize: "m",
id: "record_file",
name: "record_file"
}) }}
{{ tnaTextInput({
label: "Enter the name of the record",
headingSize: "m",
id: "record_name",
name: "record_name"
}) }}
{{ tnaCheckboxes({
label: "Select the record categories",
headingSize: "m",
id: "record_categories",
name: "categories",
items: [
{
text: "Architectural",
value: "architectural"
},
{
text: "Banking",
value: "banking"
},
{
text: "Charities",
value: "charities"
}
]
}) }}
{{ tnaDateInput({
label: "Enter the start date of the record",
headingSize: "m",
id: "record_date",
name: "date"
}) }}
{{ tnaRadios({
label: "Select the type of record",
headingSize: "m",
id: "record_type",
name: "type",
items: [
{
text: "Physical",
value: "physical"
},
{
text: "Digital",
value: "digital"
}
]
}) }}
{{ tnaTextarea({
label: "Enter the record description",
headingSize: "m",
id: "record_feedback",
name: "feedback"
}) }}
<div class="tna-button-group">
{{ tnaButton({
text: "Create record",
buttonElement: true,
buttonType: "submit"
}) }}
</div>
</form>
</div>
</div>
Jinja
Important information
{% from "components/button/macro.html" import tnaButton %}
{% from "components/checkboxes/macro.html" import tnaCheckboxes %}
{% from "components/date-input/macro.html" import tnaDateInput %}
{% from "components/file-input/macro.html" import tnaFileInput %}
{% from "components/radios/macro.html" import tnaRadios %}
{% from "components/textarea/macro.html" import tnaTextarea %}
{% from "components/text-input/macro.html" import tnaTextInput %}
<div class="tna-container">
<div class="tna-column tna-column--full">
<form novalidate>
<h1 class="tna-heading-xl">Create a record</h1>
{{ tnaFileInput({
"label": "Upload the record",
"headingSize": "m",
"id": "record_file",
"name": "record_file"
}) }}
{{ tnaTextInput({
"label": "Enter the name of the record",
"headingSize": "m",
"id": "record_name",
"name": "record_name"
}) }}
{{ tnaCheckboxes({
"label": "Select the record categories",
"headingSize": "m",
"id": "record_categories",
"name": "categories",
"items": [
{
"text": "Architectural",
"value": "architectural"
},
{
"text": "Banking",
"value": "banking"
},
{
"text": "Charities",
"value": "charities"
}
]
}) }}
{{ tnaDateInput({
"label": "Enter the start date of the record",
"headingSize": "m",
"id": "record_date",
"name": "date"
}) }}
{{ tnaRadios({
"label": "Select the type of record",
"headingSize": "m",
"id": "record_type",
"name": "type",
"items": [
{
"text": "Physical",
"value": "physical"
},
{
"text": "Digital",
"value": "digital"
}
]
}) }}
{{ tnaTextarea({
"label": "Enter the record description",
"headingSize": "m",
"id": "record_feedback",
"name": "feedback"
}) }}
<div class="tna-button-group">
{{ tnaButton({
"text": "Create record",
"buttonElement": True,
"buttonType": "submit"
}) }}
</div>
</form>
</div>
</div>
Headings
Most form fields have support for a headingLevel property which adds a <h1> to <h6> to the form label which allows screen reader users to jump to different fields based on the headings.
If there is a single field on the page, use an <h1> in its label.
<form>
<h1>
<label for="email">Enter your email</label>
</h1>
<input id="email">
</form>
If there are multiple fields, use an <h1> outside the form fields.
<form>
<h1>Create a new user</h1>
<label for="new-username">Enter a username</label>
<input id="new-username">
<label for="new-email">Enter an email</label>
<input id="new-email">
</form>
If there are multiple forms on the page, consider adding heading levels for secondary forms. If there is a single field, use a heading for the field label and if there are multiple fields, use a separate heading.
<form>
<h1>Create a new user</h1>
<label for="new-username">Enter a username</label>
<input id="new-username">
<label for="new-email">Enter an email</label>
<input id="new-email">
</form>
<form>
<h2>
<label for="search-username">Search for a user by username</label>
</h2>
<input id="search-username">
</form>
<form>
<h2>Submit feedback</h2>
<label for="feedback-email">Enter your email</label>
<input id="feedback-email">
<label for="feedback-feedback">Enter your feedback</label>
<textarea id="feedback-feedback"></textarea>
</form>
Autocomplete
Use the autocomplete property to help people fill in forms with their own data. See the list of input purposes on w3.org.
If you are working in production you’ll need to do this to meet WCAG 2.2 success criterion 1.3.5 Identify input purpose.
You will not normally need to use the autocomplete attribute in prototypes, as users will not generally be using their own devices.
HTML
<div class="tna-container">
<div class="tna-column tna-column--full">
<form novalidate>
<h1 class="tna-heading-xl">Create an account</h1>
<div class="tna-form-item">
<div class="tna-form-item__header">
<label class="tna-form-item__label tna-heading-m" for="firstname">
Enter your name
</label>
</div>
<div class="tna-form-item__body">
<input id="firstname" class="tna-text-input" name="firstname" value="" type="text" spellcheck="false" autocapitalize="off" autocorrect="off" autocomplete="name">
</div>
</div>
<div class="tna-form-item">
<div class="tna-form-item__header">
<label class="tna-form-item__label tna-heading-m" for="email">
Enter your email address
</label>
</div>
<div class="tna-form-item__body">
<input id="email" class="tna-text-input" name="email" value="" type="text" spellcheck="false" autocapitalize="off" autocorrect="off" autocomplete="email">
</div>
</div>
<div class="tna-form-item">
<div class="tna-form-item__header">
<label class="tna-form-item__label tna-heading-m" for="country">
Enter your country
</label>
</div>
<div class="tna-form-item__body">
<input id="country" class="tna-text-input" name="country" value="" type="text" spellcheck="false" autocapitalize="off" autocorrect="off" autocomplete="country">
</div>
</div>
<div class="tna-button-group">
<button class="tna-button" type="submit">
Create record
</button>
</div>
</form>
</div>
</div>
Nunjucks
{% from "nationalarchives/components/button/macro.njk" import tnaButton %}
{% from "nationalarchives/components/text-input/macro.njk" import tnaTextInput %}
<div class="tna-container">
<div class="tna-column tna-column--full">
<form novalidate>
<h1 class="tna-heading-xl">Create an account</h1>
{{ tnaTextInput({
label: "Enter your name",
headingSize: "m",
id: "firstname",
name: "firstname",
autocomplete: "name"
}) }}
{{ tnaTextInput({
label: "Enter your email address",
headingSize: "m",
id: "email",
name: "email",
autocomplete: "email"
}) }}
{{ tnaTextInput({
label: "Enter your country",
headingSize: "m",
id: "country",
name: "country",
autocomplete: "country"
}) }}
<div class="tna-button-group">
{{ tnaButton({
text: "Create record",
buttonElement: true,
buttonType: "submit"
}) }}
</div>
</form>
</div>
</div>
Jinja
Important information
{% from "components/button/macro.html" import tnaButton %}
{% from "components/text-input/macro.html" import tnaTextInput %}
<div class="tna-container">
<div class="tna-column tna-column--full">
<form novalidate>
<h1 class="tna-heading-xl">Create an account</h1>
{{ tnaTextInput({
"label": "Enter your name",
"headingSize": "m",
"id": "firstname",
"name": "firstname",
"autocomplete": "name"
}) }}
{{ tnaTextInput({
"label": "Enter your email address",
"headingSize": "m",
"id": "email",
"name": "email",
"autocomplete": "email"
}) }}
{{ tnaTextInput({
"label": "Enter your country",
"headingSize": "m",
"id": "country",
"name": "country",
"autocomplete": "country"
}) }}
<div class="tna-button-group">
{{ tnaButton({
"text": "Create record",
"buttonElement": True,
"buttonType": "submit"
}) }}
</div>
</form>
</div>
</div>
Background colours
Don’t use forms within sections that use either accent or light accent block colours. Use only plain, tinted or contrasting backgrounds.