Web accessibility means people can perceive, understand and operate an interface across different devices and abilities. It is not a badge added after development. The most reliable approach starts with semantic HTML, preserves keyboard behavior, provides clear labels and errors, and tests the real workflow rather than only running an automated scanner.
This guide focuses on decisions frontend developers make every day: choosing a button instead of a clickable container, associating a label with a field, maintaining visible focus and using ARIA relationships without replacing native behavior. Accessibility and performance reinforce each other when a page uses lean semantic markup. The frontend audit checklist shows how to test both in one release workflow.
Start with native HTML semantics
Native elements communicate role and behavior to browsers and assistive technology. A button is focusable, exposes a button role and responds to expected keyboard input. A div with a click handler provides none of those behaviors automatically. Adding role="button" changes exposed semantics, but developers must still implement keyboard operation, focus styling and disabled behavior.
| User need | Prefer | Avoid as a shortcut |
|---|---|---|
| Perform an action | <button> | Clickable <div> |
| Navigate to a URL | <a href> | Button with manual location change |
| Enter a value | Appropriate native input and label | Custom editable container |
| Organize a page | Landmarks and heading hierarchy | Visual size alone as structure |
Use header, nav, main, aside and footer for meaningful regions. Keep one logical heading outline. Do not choose a heading level because of its default font size; use CSS for appearance.
Accessible names and descriptions solve different problems
An accessible name identifies a control. A description supplies supporting information. Visible text associated with native markup is usually the clearest name. For a form field, a label whose for value matches the input id gives both a visual and programmatic relationship.
aria-describedby references existing elements that explain a control, such as format guidance or an error. It does not replace the label. If visible text already names a control, avoid adding a different aria-label that creates a mismatch between what sighted users see and what assistive technology announces.
Build an understandable form
The following example represents an invalid submitted state. In a real form, add aria-invalid and the error message only when validation has actually failed. Keep useful instructions available before the error occurs.
<form novalidate>
<label for="email">Work email</label>
<input
id="email"
name="email"
type="email"
required
aria-invalid="true"
aria-describedby="email-hint email-error"
>
<p id="email-hint">
Use the address where you receive project updates.
</p>
<p id="email-error" role="alert">
Enter a valid email address.
</p>
<button type="submit">Create account</button>
</form>
Do not use placeholder text as the only label. It disappears during entry, often has weak contrast and does not provide the same persistent instruction. When submission fails, present a useful summary, identify each invalid field and move focus only according to a tested, predictable strategy.
Make every workflow keyboard operable
Keyboard testing is more than pressing Tab until the footer. A person must be able to reach controls, understand the current focus, activate them, escape temporary surfaces and continue in a logical order. Avoid positive tabindex values that manually reorder focus; align DOM order and visual order instead.
- Start at the browser address bar and navigate with Tab and Shift+Tab.
- Confirm every interactive control has a visible focus indicator.
- Use Enter and Space according to the control type.
- Open dialogs, menus and disclosures, then test their documented keyboard pattern.
- Close temporary UI and verify focus returns to a sensible trigger.
- Check that sticky headers or overlays do not obscure the focused item.
A focus trap is appropriate inside a correctly implemented modal dialog while it is open, but a user must be able to close that dialog. Do not trap keyboard users in a custom widget or remove focus outlines without providing an equally visible replacement.
Use ARIA to express missing semantics
ARIA is valuable for relationships, states and composite widget patterns that HTML alone cannot express. It does not change visual appearance or automatically add event handling. A tab interface needs roles and selected state, but it also needs arrow-key behavior, focus management and panels associated with their tabs.
- Prefer a native element when it provides the required semantics and behavior.
- Keep ARIA state synchronized with visible state.
- Reference IDs that exist and remain unique.
- Do not hide a focusable control with
aria-hidden="true". - Follow an established Authoring Practices pattern for a complex widget.
Images need purposeful alternatives
An informative image needs text that conveys its purpose in context. A chart should also have a nearby summary of the important values or conclusion. A linked image needs an alternative that describes the link destination or action. Pure decoration should use an empty alt attribute so it is ignored.
Responsive delivery does not change those requirements. The responsive images guide explains how to combine useful alternatives with intrinsic dimensions, srcset and modern formats.
Use layered testing
| Method | What it reveals | What it cannot prove alone |
|---|---|---|
| Automated scan | Detectable markup and contrast rules | Complete usability |
| Keyboard walkthrough | Reachability, focus order and traps | Screen-reader wording |
| Accessibility tree | Exposed names, roles and states | All real assistive-technology behavior |
| Zoom and reflow | Clipping, overlap and responsive reading | Every device configuration |
| Assistive-technology test | Actual workflow and announcements | Every user preference |
Include disabled people in research and usability testing where possible. Automated tools are useful regression detectors, but passing their rules does not establish conformance or a usable experience.
Common pitfalls
- Using placeholder text as the only field label.
- Adding a role without implementing the expected keyboard behavior.
- Removing focus outlines for visual style.
- Using color alone to communicate an error or status.
- Sending focus to the top of the page after every small update.
- Writing vague link text such as “click here” when the destination is unclear.
| Release check | Pass condition |
|---|---|
| Keyboard navigation | Every control is reachable, operable and visibly focused |
| Form fields | Each field has a persistent programmatic label and useful errors |
| Images | Informative images have purposeful alternatives; decorative images use empty alt text |
| Dynamic UI | Names, roles, states and focus behavior remain synchronized |
Frequently asked questions
Is placeholder text an accessible label?
No. Use a persistent visible label associated with the control. Placeholder text may provide an example, but it should not be the only name or instruction.
Does role="button" make a div work like a button?
No. It exposes a role but does not add focusability, keyboard activation, form behavior or disabled semantics. Prefer a native button.
Should decorative images describe their colors and shapes?
No. If an image adds no information or function, use an empty alt="" so assistive technology can ignore it.
Authoritative references
Test your frontend skills
Apply semantic HTML, ARIA relationships, performance, React and responsive-image knowledge.
A practical assessment of Core Web Vitals, React rendering, JavaScript loading, responsive images, caching, semantic HTML, and accessible forms. Start the trivia-style player right inside the article.Modern Frontend Performance & Accessibility Mock Test



Discussion
0 comments
Ask a question or share what stood out to you.