Form instructions

Overview – Form instructions

Form instructions help users understand how to complete the form and use individual form controls. Indicate any required input, data formats, and other relevant information.

Overall instructions

Provide form instructions above the form prior to the starting <form> tag. Indicate any required and optional input, allowed data formats, timing limitations and any overall instructions that apply to the entire form.

Note: Screen reader users could easily miss overall form instructions nested in a <form> element. Screen readers enter “forms mode” once inside a form, disabling text-browsing keyboard shortcuts to enable the screen reader user to type directly into input and textarea fields. Keyboard navigation is limited to just the focusable elements (form inputs, links and other controls) via the Tab key. Text that isn’t programmatically associated with a focusable element — serving as a label or description — is easily missed.

Example form instructions:

  • All fields marked “required” must be completed.
  • Dates should all be typed in the format yyyy/mm/dd, (as in 2022/01/05).
  • Extra help can be found immediately after each field.

In-line instructions

In-line instructions are provided within or outside the label of the form control. Short instructions can fit in the label along with the control’s name. Long instructions should be outside the label, associated with the control via the aria-describedby attribute.

Providing instructions within labels

Providing instructions within labels is well-supported by user agents, though it should be reserved for shorter instructions. Match the for attribute of the label with the id attribute of the form control.

  Good example: Providing instructions within a label

The required format for the Employee ID is indicated by XX-1234 within the same label:

HTML

<label for="employee-id">Employee ID (XX-1234)</label> 
<input type="text" name="employee-id" id="employee-id">

Providing instructions outside labels

Use ARIA to provide instructions outside of labels. Associate any descriptive text in the form with the relevant form element using the aria-labelledby or aria-describedby attribute.

  Good example: Providing form control instructions using aria-labelledby

One approach to providing instructions outside of labels uses the aria-labelledby attribute on the control:

  • The <label> element is associated with its control using matching for and id attribute values.
  • The aria-labelledby attribute on the control references the id attribute values of itself and the element holding the description.

This approach guarantees the additional description is communicated to assistive tech, but should only be used with short descriptions.

 1234-567-890-XX

HTML

<label for="health-card">Health card number</label>
<input type="text" id="health-card" aria-labelledby="health-card hc-format" name="health-card">
<span id="hc-format">1234-567-890-XX</span>

  Good example: Providing form control instructions with aria-describedby

The more common approach to providing instructions outside of labels is to use the aria-describedby attribute. The attribute is set on the control and points to the id attribute value of the element containing the description.

Must contain at least 8 characters, one uppercase letter and one special character

HTML

<div class="form-group">
   <label for="password1">Password</label>
   <div>
      <input type="password" id="password1" aria-describedby="passDesc" name="password1">
      <div id="passDesc">Must contain at least 8 characters, one uppercase letter and one special character</div>
   </div>
</div>

Placeholder text

Text in the placeholder attribute provides instructions or an example of the required data format inside form fields that have not yet been edited by the user.

Note that placeholder text disappears from a form field when users start entering text. If the placeholder text contains instructional information or examples that disappear, it makes it more difficult for users to check their responses before submitting the form.

Placeholder text is not a replacement for labels. Assistive technologies such as screen readers do not treat placeholder text as labels.

HTML

<div>
   <label for="search">Search</label> 
   <input type="text" name="search" id="search" placeholder="e.g., Accessibility courses">
</div>
<div>
   <label for="email">Email</label> 
   <input type="email" name="email" id="email" placeholder="jane.doe@gmail.com" autocomplete="email">
</div>

Styling the placeholder

In many browsers, the default placeholder attribute colour fails a contrast check, making it difficult for many people to see. The colour of the placeholder can be styled using CSS.

The example below sets the foreground color to a medium gray (hex #767676) against a white background, which just meets the minimum 4.5:1 contrast ratio requirement.

View HTML
<div>
   <label for="search">Search courses</label>  
   <input type="text" name="search" id="search" placeholder="e.g., Accessibility courses">
</div>
<div>
   <label for="fname">First name</label>  
   <input type="text" name="fname" id="fname">
</div>
<div>
   <label for="lname">Last name</label>  
   <input type="text" name="lname" id="lname">
</div>
<div>
   <label for="email1">Email</label>  
   <input type="text" name="email" id="email1" placeholder="jane.doe@gmail.com"> 
</div>
View CSS
::-webkit-input-placeholder { 
   color: #767676 !important; 
   opacity: 1;
}
:-moz-placeholder { 
   /* Firefox 18- */ 
   color: #767676  !important;
   opacity: 1;
}
::-moz-placeholder {  
   /* Firefox 19+ */ 
   color: #767676 !important;
   opacity: 1;
}
:-ms-input-placeholder { 
   color: #767676  !important; 
   opacity: 1;
}

Instructions for groups

In “focus mode”, when tabbing through the form, screen reader users set focus on form controls and hear their labels and descriptions. Text in a non-focusable element is missed unless it is programmatically associated with a form control as label or description.

  Good example: Group instructions in a legend

In this example, the word “Required” is set within the <legend> to indicate that everything within the related fieldset is required. Depending on the configuration, some screen readers read out the legend either with every form element, once, or, rarely, not at all. Keep legends short and self-explanatory.

User login information (required)
View HTML
<fieldset>
   <legend class="required"> 
      User login information (Required)
   </legend>
   <label for="username" class="required">Username</label>
   <input type="text" id="username" required autocomplete="username">
   
   <label for="password" class="required">Password</label>
   <input type="password" id="password" required autcomplete="current-password">
   
   <label for="email" class="required">Email</label>
   <input type="email" id="email" required autcomplete="email">
   
   <label for="phone" class="required">Phone</label>
   <input type="tel" id="phone" required auto-complete="tel-national">
</fieldset>
View CSS
label.required:before, 
legend.required:before {
   content: "* ";
   margin-left: -0.665em;
   color: #d3080c;
   font-weight: 700;
}

 Bad example: Instructions in a paragraph not associated with a control

When instructions are in a <p> element not associated via aria-describedby, they’re easily missed by users navigating the form in the screen reader’s “forms mode”.

Create a User Account

Passwords must match

View HTML
<fieldset>
   <legend> 
      Create a User Account
   </legend>
   <p>
      <label for="username">Username</label>
      <input type="text" id="username">
   </p>
   <p>Passwords much match</p>
   <p>
      <label for="password2">Password</label>
      <input type="password" id="password2">
   </p>
   <p>
      <label for="retype">Re-type Password</label>
      <input type="password" id="retype">
   </p>
   <p>
      <label for="email">Email</label>
      <input type="email" id="email">
   </p>
   <p>
      <label for="phone">Phone</label>
      <input type="tel" id="phone">
   </p>
</fieldset>

  Good example: Shared instructions associated with multiple form fields

In some situations, shared instructions can be associated with multiple form fields.

Create User Account

Username and Password fields must NOT contain special characters

View HTML
<fieldset>
   <legend>Create User Account</legend>
   <p>
      Username and Password fields <span id="specialchar">must NOT contain special characters</span>
   </p>
   <p>
      <label for="username">Username</label>
      <input type="text" id="username" aria-describedby="specialchar">
   </p>
   <p>
      <label for="password3">Password</label>
      <input type="password" id="password3" aria-describedby="specialchar">
   </p>
   <p>
      <label for="email">Email</label>
      <input type="email" id="email">
   </p>
   <p>
      <label for="phone">Phone</label>
      <input type="tel" id="phone">
   </p>
</fieldset>

  Good example: Provide instructions in plain text before the form

In this example, general form instructions precede the opening <form> tag, where screen reader users can easily access them. If the plain text instructions were inside the <form> element, users could easily miss them since navigation inside a form is limited to focusable elements (aka ”forms mode”).

Choose the source and destination accounts below to complete your funds transfer:

Transfer funds

HTML

<p>Choose the source and destination accounts below to complete your funds transfer:</p> 
<form action="/action.php" method="get">[…]</form>

Related WCAG resources

Related WCAG resources

Success criteria

Techniques

Back to top