Form part 1 - Structure your form

Associated themes :

Introduction #

For a form to be accessible to all users, a few rules must be respected during development.

We will see, in this first part, how to properly build your form, then, in a second part, the submission of a form and the validation steps.

We are going to develop a registration form in order to see all the subtleties to make a form accessible.

In this example, we used Boosted library. This allows you to obtain forms whose design complies with the Orange charter.

Label form fields #

Labels should describe the role of each field on the form. In order for all users to have access to the same information, it is important that these labels are correctly associated with their form fields. To achieve this there are several techniques.

The label element #

The preferred solution is to use the label element. It is best supported by assistive technologies. There are two ways to use this label element:

  • explicitly link the element label with its field by filling in an attribute for which will match with the id of the form field it is associated with
  • implicitly link the element label with its field, in this case, the element label will be used as a container surrounding the form field. The first solution is recommended.

Example #

Example of explicitly linked form labels :

Sample code :

  
  <form id="formulaire" class="border border-secondary p-3 my-2">
    <div class="mb-2">
        <label for="email" class="form-label">E-mail</label>
        <input type="text" class="form-control" id="email"/>
    </div>
    <div class="mb-2">
      <label for="name" class="form-label">Last Name</label>
      <input type="text" class="form-control" id="name"/>
    </div>
    <div class="mb-2">
      <label for="firstname" class="form-label">Fist Name</label>
      <input type="text" class="form-control" id="firstname"/>
    </div>
  </form>
  

Hide labels in an accessible way #

In some cases, it may be useful to hide the label visually. Attention, labels can be hidden if and only if the field function is sufficiently clear and understandable in its context: for example, a search field next to a magnifying glass icon.

Even though the label is visually hidden, it should still be accessible to assistive technologies.

This method consists of using a CSS class (using the visually-hidden class from Bootstrap/Boosted) allowing accessible hiding. Using accessible masking allows the element to be hidden from view, while retaining its vocalization by assistive tools or technologies (AT). Be careful, do not use classic CSS masking (display: none; or visibility: hidden;) because the element will also be hidden for screen readers.

See the example at accessible masking example for more information.

Example #

For example, we can use accessible hiding for a search field, if a button with the search label, or a magnifying glass image, is next to the field. Thus, the field label is visually hidden to avoid redundancy.

Sample code:

  
    <label for="recherche" class="visually-hidden">Search: </label>
    <input type="text" name="search" id="search">
    <button type="submit">Search</button>
  

ARIA attributes #

It is also possible to use the aria-label and aria-labelledby attributes to label form fields, as these attributes are well supported by browsers and in recent assistive technology:

  • The aria-labelledby attribute is used to specify the id of an element present in the code that will be used to label the field.
  • The aria-label attribute allows you to directly specify a label in the form of a character string. Please note that the information will not be given visually.

A possible example:

  
    <input type="text" name="search" aria-labelledby="search">
    <button id="search" type="submit" class="icon-loup" aria-label="Search"></button>
  

The title attribute #

The title attribute is used to label a form field in an accessible manner. It will also trigger the display of a tooltip when hovering over the element with the mouse, good thing for the cognitively impaired, digital novices.

Be careful, we might be tempted to use the placeholder attribute. This attribute is not robust enough, indeed:

  • the placeholder text that displays in the field is usually not high enough contrast;
  • it is erased when entering the content in the control (causing difficulties in the event of a deficiency cognitive);
  • the placeholder is not always read by assistive technology;
  • it makes corrections difficult in case of error if there is no label displayed;

On the other hand, the placeholder can serve as a guide, an aid to fill in the field without this information being absolutely necessary (for example, proposing a valid expected value): do not hesitate to use for this type of need.

When necessary, it is important to group fields of the same nature, this will make the whole form more understandable.
Most of the time, we group our radio buttons, or our checkboxes, in order to associate a header with these elements.

To group them, we use the fieldset element, which will have as its first child the legend element that will serve as the header for our grouped fields.

Example #

In our registration form, we can add the gender of our user. For this, we will implement radio buttons, and group them with the header Gender

[...]
Gender

Sample code :

  
    <div class="col-md-8">
    <form id="formulaire3" class="border border-secondary p-3 my-2">
      [...]
      <fieldset>
        <legend>Gender</legend>
        <div class="form-check form-check-inline">
          <input class="form-check-input" type="radio" name="inlineRadioOptions" id="M" value="M">
          <label class="form-check-label" for="M">Mr</label>
        </div>
        <div class="form-check form-check-inline">
          <input class="form-check-input" type="radio" name="inlineRadioOptions" id="Mme" value="Mme">
          <label class="form-check-label" for="Mme">Mrs</label>
        </div>
        <div class="form-check form-check-inline">
          <input class="form-check-input" type="radio" name="inlineRadioOptions" id="Non-binaire" value="No-binary" >
          <label class="form-check-label" for="Non-binaire">no-binary</label>
        </div>
      </fieldset>
    </form>
  </div>
  

Specify the expected type or format #

To help the user, it is also important to specify the expected type or format when necessary. For example, for a date of birth, you must, if necessary, indicate the input format (dd/mm/yyyy).

To inform the user, one can:

  • provide instructions in label
  • use the aria-labelledby or aria-describedby attribute

Example #

For our registration form, we are going to add a password field, specifying the format that we want.

When adding a password field, it is also important to allow the possibility of displaying or hiding the password. This allows users with motor, attention or cognitive disorders to avoid possible input errors.

Your password must contain at least 6 characters.

Sample code :

  
  <div class="col-md-8">
    <form id="formulaire4" class="border border-secondary p-3 my-2">
      <label for="password" class="form-label">Password</label>
      <div class="mb-2 input-group">
        <input type="password" class="form-control" id="password" aria-describedby="passwordHelpBlock"/>
        <span class="input-group-text">
          <button type="button" class="btn btn-icon btn-no-outline btn-sm" id="password_visibility" title="Show password" >
            <svg aria-hidden="true" focusable="false" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
              [...]
            </svg>
          </button>
        </span>
      </div>
      <div id="passwordHelpBlock" class="form-text">
          Your password must contain at least 6 characters.
        </div>
    </form>
  </div>
  

Complete example #

The complete example with all the elements that we have reviewed. In the second part, we will see how to validate the form and manage error messages.
For the rest of the exercise and to complete our registration form, we have added fields for the address (address, city, postal code).

Your password must contain at least 6 characters.
Gender

The final code :

  
  <div class="col-md-8">
    <form id="formulaire_final" class="border border-secondary p-3 my-2">
      <div class="mb-2">
        <label for="email_final" class="form-label">E-mail</label>
        <input type="text" class="form-control" id="email_final"/>
      </div>
      <label for="password_final" class="form-label">Password </label>
      <div class="mb-2 input-group">
        <input type="password" class="form-control" id="password_final" aria-describedby="passwordHelpBlock_final"/>
        <span class="input-group-text">
          <button type="button" class="btn btn-icon btn-no-outline btn-sm" id="password_visibility_final" title="Show password" >
            <svg aria-hidden="true" focusable="false" fill="currentColor" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 1000 1000"></svg>
          </button>
        </span>
      </div>
      <div id="passwordHelpBlock_final" class="form-text">
          Your password must contain at least 6 characters.
      </div>
      <div class="mb-2">
        <label for="name_final" class="form-label">Last Name</label>
        <input type="text" class="form-control" id="name_final"/>
      </div>
      <div class="mb-2">
        <label for="firstname_final" class="form-label">First Name</label>
        <input type="text" class="form-control" id="firstname_final"/>
      </div>
      <fieldset>
        <legend>Gender</legend>
        <div class="form-check form-check-inline">
          <input class="form-check-input" type="radio" name="inlineRadioOptions_final" id="M_final" value="M">
          <label class="form-check-label" for="M_final">Mr</label>
        </div>
        <div class="form-check form-check-inline">
          <input class="form-check-input" type="radio" name="inlineRadioOptions_final" id="Mme_final" value="Mme">
          <label class="form-check-label" for="Mme_final">Mrs</label>
        </div>
        <div class="form-check form-check-inline">
          <input class="form-check-input" type="radio" name="inlineRadioOptions_final" id="Non-binaire_final" value="No-binary" >
          <label class="form-check-label" for="Non-binaire_final">No-binary</label>
        </div>
      </fieldset>
      <div class="mb-2">
        <label for="adresse_final" class="form-label">Address</label>
        <input type="text" class="form-control" id="adresse_final"/>
      </div>
      <div class="mb-2">
        <label for="adresse2_final" class="form-label">Additional address</label>
        <input type="text" class="form-control" id="adresse2_final"/>
      </div>
      <div class="mb-2">
        <label for="ville_final" class="form-label">City</label>
        <input type="text" class="form-control" id="ville_final"/>
      </div>
      <div class="mb-2">
        <label for="cp_final" class="form-label">Zip Code</label>
        <input type="text" class="form-control" id="cp_final"/>
      </div>
    </form>
  </div>