Skip to content

POSH Foundations

Building accessible interfaces with semantic HTML

Theme selector

Unit 4: Links, buttons and forms

Links vs. buttons

One of the most common accessibility fails.

Please, do not code and style a div or a span to look and act like a button or link.

Links

Go somewhere - another page, another place on the same page, another view, another component.

Go to another page

Go to a section on a page

Download a file

Navigate to a new route

Buttons

Do something - open a modal, submit a form, toggle an accordion, etc.

Regular button

Submit button

Toggle button

Open a dialog button

Icon-only buttons

Aria label


Screen-reader only text

Icon-only buttons

Alt attribute


Title

Use native elements wherever possible

Native HTML elements come with keyboard support, focus styling, roles, states, and behaviors.

Fake elements require you to re-create all of that manually, and often poorly in comparison.

Native elements are flexible and can be styled with CSS.

How hard is it to fake a button?

HTML

CSS


                  .fake-button {
                    display: inline-block;
                    padding: 0.5rem 1rem;
                    background-color: #007BFF;
                    color: white;
                    border: none;
                    border-radius: 4px;
                    text-align: center;
                    cursor: pointer;
                    user-select: none;
                  }

                  .fake-button:focus {
                    outline: 2px solid #0056b3;
                    outline-offset: 2px;
                  }

                  .fake-button:active {
                    background-color: #0056b3;
                  }

                

...and you still need the JavaScript


              function handleClick(event) {
                alert('Button clicked!');
              }

              function handleKeydown(event) {
                if (event.key === 'Enter' || event.key === ' ') {
                  event.preventDefault(); // Prevent spacebar scrolling
                  handleClick(event);
                }
              }
            

The problems with fake buttons

  • You have to manually recreate behaviors that are already included with button elements.
  • It's easy to miss details - keyboard handling, stopping scrolling, etc.
  • Even when done well, behavior can still be inconsistent with different assistive tech.
  • Increasing the accessibility debt on the project every time a new fake button is added.

Accessible forms have labels

Missing form fields impact users with cognitive disabilities and low vision users, not just screen reader users.

Don't use a placeholder as a label substitute.

Explicit form label

Label is connected to the form field with a for attribute that references the id attribute of the form field:

  • label has a for="name".
  • input has id="name".
  • Screen readers announce the label when focusing the input.
  • Great for flexibility - you can place the label anywhere (even before or after the input).

Implicit form label

Input is wrapped inside the label element, so no for or id needed.

  • The input is a child of the label.
  • The browser automatically associates them.
  • Cleaner for small, simple forms (but less flexible for complex layouts).

Autocomplete

  • Help browsers fill in known values, making forms faster and easier to complete.
  • Can be used on <form>, <select>, <textarea>, and <input> elements (as long as the input type takes input.
  • Form fields should have an id and/or name attribute, and be a descendant of a <form> with a submit button.

More details about autocomplete at MDN.

Group examples


Radio buttons

Choose your preferred contact method

Checkboxes

Select your areas of interest

Address

Mailing Address

Radio button fieldset

Checkbox fieldset

Address fields

Required fields

  • Add the required attribute to form fields that are required for submission.
  • Announced by screen readers when focus lands on the input.
  • But...for an improved user experience, you probably want to handle validation with JavaScript.

Pair with a label that clearly marks the field as required.

Instructions and errors

Username must be 6–20 characters and contain only letters and numbers.

Unit 4: Links, buttons and forms

Key takeaways:

  1. Use semantic interactive elements.
  2. Native HTML means getting your accessibility for free.
  3. Use the correct element.
  4. Audit forms and buttons on your own sites - they are low-hanging fruit with big impact.