Building Accessible Forms in Front-End Applications
How to make forms accessible to everyone. It’s easier than you think
Forms are crucial components of the web as they help collect user information to achieve what the user wants to. Sometimes, due to the developer's ignorance, forms are difficult to complete for normal users which makes it ten times harder for users with disabilities.
Most people with disabilities, especially those with vision disabilities, have difficulty using forms. Navigating through a web page with text content is one thing, moving through form fields and providing valid data is another thing entirely.
You will want to make sure all of your users are able to use your forms without having a horrible experience, regardless of their conditions. We can do that by simply making the form accessible.
Before we proceed, we need to understand what we mean by making the form accessible or web-accessible and web accessibility.
In a simple sentence, making a form accessible means anyone with any kind of disability (not necessarily physical disabilities) will be able to interact with forms.
Web accessibility simply means making the web accessible to everyone and anyone. I wrote an article on web accessibility and how to make the web accessible. You can read it by following the link above.
In modern applications, it often takes more steps to adhere to A11Y guidelines due to the modern complex user interface and experience we want to achieve, thereby trading off web accessibilities.
There are ways you can implement your complex UI/UX and still adhere to the guidelines without trading off anything, thereby making the web more accessible.
In this article, we’ll explore how to build web accessible forms in front-end applications. These apply to all front-end applications built with React, Vue, Svelte, or even static sites.
Use Native Form Tags
Yes, please use the native form tags. Ensure you wrap your inputs in a form
tag, use the right input tag for the right use case. This might seem insignificant but in reality, it is very important.
Your input
, select
, and textarea
tag should be wrapped in the form
for accessibility reasons. By default, the browser automatically triggers the submit event by either clicking on a button
tag in the form or pressing the Enter
key on a keyboard.
Ensure you use the right input type for the right data you want to collect. For instance, if you want to collect email data, the right input type for that is email
because you get native email validation from the browser.
The same goes for the password fields, checkboxes, radio buttons, and others.
Below is some example code of a form using native forms.
Try not to reinvent the wheel and use the native form tags. The default HTML tags usually come with accessibilities in mind. When building complex custom components, try using the default input tags anywhere possible.
What you get by using native forms:
- Native form validation.
- Keyboard accessibility.
- Native form submission.
Always Use Labels
You must ensure that all form fields have accurate labels so screen reader users know what each field is asking for. This is one of the important guidelines you should adhere to.
Forms without labels aren’t web-accessible. Each form field or input field should have its own explicit label. Let the user know what the fields are that they are about to fill.
By default, you can associate form controls with the <label>
tag using the for
attributes in normal HTML and htmlFor
in React to the id
of the control, or by basically wrapping the input tag inside the label tag.
Labels should generally describe the function of each form field/control.
Ensure the label is adjacent to its respective form control. Labels are usually positioned above or to the left of the controls, however, the labels for checkboxes and radio buttons are usually to the right of the control.
Labels automatically set focus on associated form controls by clicking on them and in case of checkboxes and radio boxes, it basically triggers onClick
events.
Use onSubmit Event When Submitting Form
When submitting any type of form in front-end applications, ensure you use the onSubmit
event.
By default when you press the Enter
key on the keyboard or click on the <button>
or <input type="submit" />
, it automatically triggers the browser’s onSubmit
event which makes it easier to submit forms in the browser.
In native forms, to submit a form you need to provide method
attributes and action
attributes.
The method
attributes are used to specify whether to submit the form using the GET
or POST
methods while action
attributes are where the form data and request will be sent to.
For instance, to create a form to search on Google:
This basically opens a new Google search page: https://google.com/search?q=<search_query>
.
When working with forms in front-end applications, avoid using onClick
events on buttons to submit the form. Users using theEnter
key to submit wouldn’t be able to submit the form because that wouldn’t trigger the onSubmit
event.
Below is an example of a form using the onSubmit
event in a React application:
In the simple form, you can submit the form either using the Enter
key or clicking on the search button.
If you are using the button
tag to serve as the submit button, either leave it the way it is or add type="submit"
to the button
tag. If you want to use the input
tag instead, then you must add the type="submit"
attribute.
Keyboard Accessible
Ensure forms are keyboard accessible. Make sure forms can be used by users who can only navigate your website with a keyboard.
Many users can only use a keyboard to navigate and use the web. You must ensure that the forms on your web site can be completed using only the keyboard.
When using JavasScript on forms for manipulating data, setting focus, or manipulating form controls, ensure the form is usable with the keyboard.
Avoid tampering with the tabindex
attributes on form controls. Using it incorrectly would literally make form controls with the keyboard. If you want to use tabindex
, ensure the form controls are on the right and won’t confuse users.
Most people find the keyboard easier to navigate the form and the accesskey
attributes make it easier for users to focus on a field with a shortcut key.
<form><label>Phone: <input type="tel" accesskey="p" tabindex="1" /></label></form>
Grouping Form Controls
Grouping related form field data really gives a good experience in completing a form.
For instance, the group field’s name (first, last, middle, title, etc.) or address (address 1, address 2, city, state, postal code, country, etc.) makes it easier for users to complete a form, thereby making the form accessible.
The best way to group a form field is by using the fieldset
tag and also visually putting them in form grids.
This can also be useful in disabling a group of fields. If you add the disable
attribute to the fieldset
element, all inputs wrapped inside the element will be disabled automatically.
Form Validation and Error Messages
This is a very important aspect of an accessible form. When working with forms, ensuring the user is submitting valid information is crucial. You need to help users validate information to avoid mistakes and error messages from the back-end server handling the form data.
By default, HTML5 defines a range of built-in functionalities to validate common types of input, such as email addresses, dates, and so on. Though, you might need pattern matching and sometimes scripts to validate a custom data type.
When implementing custom validation, you need to provide enough information in an accessible way to help the user get past that, fast.
In modern applications, client-side validation isn’t enough to ensure the server validation always kicks in on any data passed by the front end and always returns enough information about the error messages and validation errors.
Most HTML5 form control has native validation and really, you do not need to do anything except validate custom data or if you want custom validation.
For instance, when validating a required field, adding the required
attributes automatically sets aria-required
to true, which makes it accessible to screen readers.
Validation errors are usually adjacent to the form control with the wrong data. Either at the top or bottom of the form control. They should be visually identified with the text color red
or any related color.
Error messages are brought to the top of the form. Error messages should be short and easy to understand.
The credit card field is a custom data that needs custom validation, either using JavaScript or pattern
attributes which will natively ensure that the entered data matches with the given pattern.
Using Aria-* (A11Y) Attributes
The aria-*
attributes are HTML attributes provided by WAI-ARIA that help to make web content more accessible for everyone including people with disabilities.
Most of the time, you really don't have a need for this, your basic HTML is enough to be accessible and you’ll only use it when working with dynamic content in complex user interfaces.
Likewise, when working with forms, you’ll only need this when working with forms programmatically.
There are various useful ARIA attributes with different uses, let’s take a look at the list below:
aria-label
: This is used in place of no label tag in a form.aria-labelledby
: Witharia-labelledby
, the form field indicates which element labels it by referencing its ID attribute.aria-describedby
: ARIA provides thearia-describedby
attribute to directly associate the description with the control.aria-valid
: To indicate if the form is valid or not to screen readers.
Tools
- Web accessibility solution: accessiBe.com — our favorite pick.
- Axe — testing tool.
- Contrast-Finder by Tanaguru.
- WAVE by WebAIM.