Accessibility Guide for Developers


  • How to create a form that is usable and accessible for most people?
  • How to develop so that your forms comply to the global Web Content Accessibility Guidelines (currently WCAG 2.1 AA)?
  • How to keep your forms accessible while adding CSS and Javascript for special styling of form controls and interaction?
  • What is important to structure your form elements? How to display and announce errors and notifications for everyone?

These are all questions you may have and that we’ve all had about form or web accessibility in general.

The web is accessible by nature. If you use valid HTML5 for your forms; interfaces like a keyboard, a mouse, a screen reader, and voice recognition software already have good access to the functionality of your forms. But HTML5 may not be enough for your application needs and accessibility requirements.

This documentation gives you an overview of what is important to maintain form accessibility and how to validate and test your output. This document will also cover where to find good documentation on components, best practices, and form accessibility.

Please also check our documentation geared towards content managers.

The World Wide Web Consortium (henceforth in this document referred to as W3C) also provides good information in their Web Accessibility Tutorials on form accessibility in Forms Concepts.

As Gravity Forms extends its accessibility, more and more of the guidelines and good practices will be implemented, so keep an eye on the accessibility mentions in the changelog with each plugin update.

Labels and Placeholders


Every form control needs a visible label and that label needs to be attached to the corresponding form control by a for/id construction.

A label is for text only. Don’t add links, buttons, tooltips, or other non-text elements inside a label element. Doing so makes it difficult for people to activate the form input associated with the label with assistive technology. See Accessibility concerns on the MDN page about labels.

A label is not the same as a placeholder. According to the HTML specifications on placeholders: the placeholder attribute is a string that provides a brief hint to the user as to what kind of information is expected in the field. It should be a word or short phrase that demonstrates the expected type of data, rather than an explanatory message.

Place labels and sub-labels above or next to the input fields. This is the natural order people read and will prevent confusion.


  • When the label is always visible, people don’t forget what they have to fill out when they are typing.
  • When the form inputs are filled with autocomplete, the users can better check if the input is added to the right input field when the label stays visible.
  • If the label is connected to the form control, screen readers will announce the label with the input field, so blind users know what to fill out.
  • If the label is connected to the form control the click target will get larger, because you can click on the label and then the input field will get focus too.
  • The placeholder is used as a suggestion on how to fill out an input field. When a user starts typing it disappears, so if it is used as the only label, the user can get confused on what to fill out.


<label for="unique-id-for-name">Your name</label>
<input type="text" id="unique-id-for-name" name="full-name" autocomplete="name" placeholder="For example Jane Doe">
<label for="unique-id-for-amount">Amount</label>
<select name="amount" id="unique-id-for-amount">
    <option value="one">One</option>
    <option value="two">Two</option>
    <option value="three">Three</option>

Make sure HTML IDs are always unique to the page. This is important for assistive technology, so they can target a specific element by its (related) id.


Grouping of elements


Group elements that belong together with a fieldset and a legend. This is useful for groups of radio buttons, checkboxes, and related fields for a name or address. A fieldset is a container for the grouped elements, a legend is the description (name) of the group.


  • By adding a fieldset and a legend, you add semantic meaning to the elements inside, they belong to each other.
  • Screen readers announce that it’s a group and announce the legend, so blind users understand the context of what they need to fill out or check on the form.


    <legend>How many cookies?</legend>
    <label for="unique-id-for-amount">Amount</label>
    <select name="amount" id="unique-id-for-amount">      
        <option value="one">One</option>    
        <option value="two">Two</option>    
        <option value="three">Three</option>      
    <legend>Select a T-shirt size</legend>
    <input id="size-s" name="size" type="radio" value="small" />
    <label for="size-s">Small</label>
    <input id="size-m" name="size" type="radio" value="medium" />
    <label for="size-m">Medium</label>
    <input id="size-l" name="size" type="radio" value="large" />
    <label for="size-l">Large</label>


MDN on fieldsets



Avoid using a positive tabindex on form controls. Keep the natural tab order intact.


Some users can’t use a mouse, this could be because they are blind or their motor skills may be impaired. Users like this can use the keyboard to navigate a website. If you use the tab key you can jump from focusable element to focusable element (like a link, button, or a form element).

If you add a positive tabindex to a form element, that element will be the first that gets focus on a page. By doing this you are hijacking the natural focus order of the page, this can be very annoying and frustrating for someone who is navigating the site with a keyboard and just wants to access the main menu and not subscribe to your newsletter on every single page.

Give the user control and don’t decide for them.

Color Contrast


The contrast between text and its background has a luminosity contrast ratio of:

  • 4.5 : 1 for normal text up to 24 pixels
  • 3 : 1 for bold text of 19px and larger
  • 3 : 1 for normal text of 24px and larger

This contrast rule does not apply to text in existing brand logos, but it does apply to other images with text. Don’t worry, there are numerous color contrast checkers, online, offline, and integrated into many design applications.

Since WCAG 2.1 AA the contrast between active user interface components, like borders of an input field and its background has a luminosity contrast ratio of 3 : 1. “Active user interface components” are for example the borders of input fields and textareas.

Note: If you style the CSS for the placeholder text, please keep in mind that some browsers add opacity by default. So with the placeholder CSS also add opacity: 1; to be sure the color is consistent in all browsers.

The placeholder also needs to have a color contrast ratio of 4.5:1 against its background.


Not everybody has perfect eyesight. By giving text and borders a good color contrast against its background, you are assuring most people can find and read the text, even with an iPad in the sun.


Use of Color


Don’t give meaning to color. Examples of this include only using a red border to indicate a field is required and still needs to be filled out, or referring to a green button in your site copy.


8% Of all men and 0.4% of all women are color blind, these people could miss the change in color or the meaning it has.

Color also doesn’t mean the same in every culture, for example, red is a warning color in Europe but a color of happiness in Japan. Don’t expect and assume people to perceive and interpret color the way you do. It’s ok if you want to add color, just don’t make it the only way to indicate something. For example, add text for an error warning explaining what the error is and how to fix it.


Note: The autocomplete rules are added in WCAG 2.1 AA: Success Criterion 1.3.5 Identify Input Purpose. If your site needs to comply with WCAG 2.0 AA only, this rule does not need to be met.


Identify the input purpose by adding an attribute with the purpose of the field to the form control. The W3C published a list of input control purposes that serves as a good resource for this.

Note: This is meant only for their own personal information of the person filling out the form.


This rule is added to help people with cognitive disabilities. It can be very useful to have a regulated form of autocomplete so people don’t have to type all of their information again and again for every form. If all forms use the same autocomplete values, it makes it easier for browsers to autofill these fields correctly and consistently.

Also, this attribute can be useful in the future for assistive technology. For example, a specific icon can be added to a label, so it’s more clear what to fill out for people who can not read that well.


<label for="fname">First Name</label>
<input id="fname"type="text"autocomplete="given-name"... >
<label for="lname">Last Name</label>
<input id="lname"type="text"autocomplete="family-name"... >


Consider carefully which fields you give an autocomplete attribute and which fields you do not. Some fields, like credit card data can be too sensitive to autocomplete and some fields may be too private to share on a public computer.

As this is a new rule, the implementation and way of reviewing are still in their early stages. Autocomplete values are very United States focused in general, the structure of names in Europe may be different than the options provided by the W3C.


Keep Non-Form Information Out of a Form

Best Practice

Keep headings, HTML blocks, standalone paragraphs, and other non-form-related information outside of a form.


Assistive technology like screen readers jump into “form mode” when they enter a form. This means that they only target focusable elements. This is done to enable the user to type characters inside input fields (instead of using them for shortcodes and navigation).

The disadvantage of this is that the screen reader doesn’t announce content that is not associated with form controls, so a heading or pieces of other HTML inside a form are not announced.

About aria-describedby

You can associate separated content to an input field with aria-describedby.

Descriptions you add to a form control with the Gravity Forms admin interface are connected to a form control with an aria-describedby construction. This makes for a description that is announced with the form control.

Note: The first rule of ARIA is: don’t use ARIA. Use it only if you don’t have another option available with HTML5.


  • The text that needs to be announced with the input field is put in a separate element, with a unique id.
  • With the input field that element is connected with an aria-describedby attribute referring to that unique id.
<label for="input_1_1">Color</label>
<input name="input_1" id="input_1_1" type="text" value="" aria-describedby="gfield_description_1_1">
<p id="gfield_description_1_1">Please fill out your favorite color</p>

Show Essential Information by Default

Good Practice

Show essential information by default and don’t hide it behind a toggle or tooltip.


Toggles, dropdowns, and tooltips are extra hurdles people need to jump through to get information, these add to the cognitive load. There is a risk people won’t get the pattern of hiding you had in mind. If information is essential to fill out a form, best not to hide it by default. You want people to fill out your form as easily as possible.

Announce Dynamic Changes


If important content changes dynamically without a page reload, announce it by using aria-live on the element that contains the change. Or use role=”alert” on a newly created element with the change.


If information changes dynamically on a page, for example, the sum of a calculation, a blind visitor may miss that information. Someone who is blind can not see the content. If the content of the change is a lot of text, like a list of form errors, then you don’t have to announce everything. You can just announce for example “The form could not be sent, there are form errors, listed above the form.” Then the screen reader user knows there are errors and where to find them.

Examples of aria-live and role=”alert”

Use aria-live for changes inside an element that is already in the DOM, the total price for example.

The screen reader listens to the content inside an element with the attribute aria-live and announces any change in content.

  • aria-live=”polite” announces the change after the users stops interacting with the webpage.
  • aria-live=”assertive” announces the change immediately.
<div aria-atomic="true" aria-live="polite">
   <label for="input_44_2">Total</label>
   <input readonly="readonly" name="input_2" id="input_44_2" value="0,00 €">

Use role=”alert” on an element that is newly created in the DOM:

<div class="validation_error" role="alert">There was a problem with your submission. Errors have been indicated below.</div>


Time Limits on a Form Submission


If you set a time limit on form submission, inform the user about this and give them an option to extend the limit before the time expires.


People with anxiety could have difficulties reacting to a sudden expiration warning. People who have a hard time filling out the form may need more time than has been given.

To help you can inform users beforehand that:

  • There is a limited time to fill out a form.
  • Why there is a lime limit (for example for security reasons).
  • And mention there is the option to extend the time if needed.

Form Validation


Help your users to avoid errors and if they occur, guide them to fix the errors.

  • Test your forms thoroughly, for various scenarios. User test if you have the resources to do so.
  • Write clear warning and error messages to guide your users.
  • Write messages in plain text that is understandable by non tech persons.
  • Add the list of the form submission errors above the form (not inside the form) and also add with each form control what went wrong.
  • If a field requires a specific format or requirement (like a date or password), provide the user with the rules, a pattern or example in the description, so they don’t have to find this via trial and error.

The W3C website published a great tutorial on how to set up notifications.


Not all your users are as web savvy as you are, don’t expect users to understand how a form is set up. Guide them through the errors and warnings and don’t blame them for not getting it right away. Be polite and understanding. And test!

Custom Styling for Select, Radio Buttons, and Checkboxes


All functionality must work with a keyboard and must be properly announced by a screen reader. As we mentioned earlier in this documentation:

“The web is accessible by nature. If you use valid HTML5 for your forms, then interfaces like a keyboard, a mouse, a screen reader and voice recognition software have access to the functionality.”


Users with assistive technology, like a screen reader or a keyboard only, must be able to fill out a form too. But the code also must be robust, ready for new and future technology.

The Problem

You want to make it pretty using CSS and Javascript. You can do that and keep the controls accessible, but you have to make sure you don’t disable keyboard and screen reader accessibility.

A popular library with styling for select form controls is Select2. At the moment Select2 is not accessible for screen readers. The selected options are not announced, so a screen reader user has no idea what to select. There is a long-standing open accessibility issue on the Select2 repository in GitHub for this.

Some patterns to create custom radio buttons that put a CSS display:none property on the input field, which makes it impossible for a keyboard user to access and select it.

The Solution

There are good patterns to create custom-styled select, radio buttons, and checkboxes. But at the moment of writing this, it’s impossible to style option elements in an accessible way with CSS only. There are requests to browser vendors to change this. Your endorsement for this is very welcome.

Good pattern libraries for styling form controls:

Discussion about styling selects

As we are waiting for browsers to permit styling to the select options, please keep this rule in mind:

Make it work before you make it nice.

A form control must work; that’s its main purpose. Making it nice is an extra.

Who is Responsible for the Web Accessibility of a Website?

As a theme or plugin developer you need to give the content managers the best tools to create an accessible form. So, not only deliver a good product but also instruct the content manager on how to keep a form accessible. For example by instructing them not to hide or omit form labels. Point them to our accessibility documentation geared towards content managers specifically. But in the end, the site owner is responsible for the accessibility of their site.

What to Do if you Find an Accessibility Issue

Did you find an accessibility issue in the Gravity Forms plugin code? Please contact us, and we’ll be happy to help you and try to solve the issue.

If you had your website audited for accessibility guidelines and there were issues reported with a form made with Gravity Forms, please let us know, so we can help you and see if the issues can be addressed by you or need changes from our side.

Validation and Testing

How do you test the accessibility of your form?

There are 3 important things to keep in mind:

  • The HTML must be valid and error free
  • All functionality must work with a keyboard only
  • Run accessibility test tools.

You should always check all three. Automated testing can not catch everything. The test tools improve but, at this moment you still have to test with a keyboard manually.

Your best test against the WCAG 2.1 AA guidelines. These are (or will be) the accessibility guidelines in most countries. When in doubt about which rules to follow, check the W3C website about Web Accessibility Laws & Policies and check with your government.

The normal automated testing for PHP and Javascript (like the tests done for the WordPress coding standards) tests the codebase itself. This is a good start, but testing for accessibility also requires that you test the generated DOM, so you have to test in the browser or in the case of automated testing use a generated instance of the DOM.

Make accessibility testing part of your test routine during development. It improves the quality of your code and it also makes you a better developer.

Tools For Testing

Your Keyboard

Use your own keyboard to test if every essential functionality works with a keyboard only. On WebAIM there is a great manual on how to do this: Keyboard Accessibility

The W3C Validation Service

Is your HTML valid and error-free? On the W3C Markup Validation Service, you can validate your generated code by URI, File Upload, and by Direct Input. To also check your CSS there is the W3C CSS Validation Service.

aXe Developer Tools

aXe Developer Tools are developed by Deque Systems, based on axe-core. At the moment this is the best and recommended accessibility check tool for developers and can easily be used during development.

  • aXe for Web is a browser extension by Deque for Chrome and Firefox that adds a tab to your inspector. You can analyze the current webpage for violations and best practices.
  • axe-cli provides a command line interface for axe-core to run accessibility tests.

Other Automated Checkers

  • HTML_CodeSniffer adds a bookmarklet that displays a popup with the errors and warnings.
  • Wave is a browser addon developed by WebAIM for FireFox and Chrome.
  • Lighthouse performs accessibility checks on a web page. Lighthouse uses axe-core as engine for the checks.

JavaScript Checkers

  • eslint-plugin-jsx-a11y: by Ethan Cohen. Static AST checker for a11y rules on JSX elements.
  • react-a11y by ReactJs. Warns about potential accessibility issues with your React elements.

Accessibility Checklists and Quick References

Resources and Pattern Libraries

Recommended reads on (form) accessibility, usability, and good practice in general.

Last Takeaway

One “rule” for web development and accessibility is :

If something is very hard to develop and to make accessible, it’s probably also too complicated for all users to understand.

Always keep your users in mind: you are not your user. Keep a form as intuitive as possible to fill out.

Don’t reinvent the wheel, stick to form design conventions. People are used to these conventions and don’t want to have to think about how to use a control they’re not familiar with. Complex constructions often have a higher learning curve to understand.

You want something from your visitors: information, an order, a subscription. Make the process for them as easy as possible. This doesn’t mean your forms have to look plain and ugly, it just gives you an opportunity to really think about functional design, usability, workflow, and simplicity to use. Knowing Web Accessibility will make you a better UX-er, designer, developer, and content writer.

Good luck!