ScreenshotNeo

BlogGuides

Web Accessibility Guide for Front-End Developers

Build accessible front ends with semantic HTML, usable keyboard interactions, clear forms, and a testing process that goes beyond automated scans.

By the ScreenshotNeo team4 October 202610 min read

Accessible front ends let people perceive content, operate controls, understand what is happening, and use the page with different browsers and assistive technologies. Start with semantic HTML and native controls, make every interaction work by keyboard, give images and controls meaningful alternatives and names, build clear form feedback, and test with people-oriented checks as well as automation. Use WCAG 2.2 as the requirements baseline for the project; do not treat a scan or a named technique as proof of conformance.

This guide is for developers building or maintaining websites and applications with HTML, CSS, JavaScript, forms, and interactive components. It focuses on implementation and repeatable testing, while distinguishing requirements from practical patterns.

1. Know the requirements and guidance

WCAG 2.2 is the normative baseline. It organizes accessibility around four principles: content must be perceivable, operable, understandable, and robust. Its success criteria state requirements. Decide which conformance level applies to your project based on its legal, contractual, or organizational requirements; do not imply a level that has not been assessed.

The ARIA Authoring Practices Guide (APG) provides patterns and examples for common widgets. It is useful implementation guidance, not a conformance standard. W3C explains: “The accessibility guidance in the APG is different from accessibility requirements specified by WCAG and ARIA.” Likewise, WCAG techniques are examples of ways to meet criteria, not mandatory recipes. Another implementation can conform if it genuinely meets the applicable success criteria.

2. Start with semantic HTML and native controls

Use elements for their intended purpose: headings for headings, links for navigation, buttons for actions, and native form controls for data entry. A native button already supports expected semantics and keyboard operation. Turning a div into a button means you must recreate those responsibilities yourself.

<main>
  <h1>Account settings</h1>
  <form>
    <label for="email">Email address</label>
    <input id="email" name="email" type="email" autocomplete="email" required>
    <button type="submit">Save settings</button>
  </form>
</main>

Keep the source order and interaction order coherent. Structure pages with headings and landmarks so users can understand and navigate them. Use a skip link when it helps users bypass repeated navigation. Set the document language, for example <html lang="en">, and use descriptive link text that makes sense out of context.

When a custom control is necessary, first write down its role, accessible name, state or value, and keyboard interaction model. Then decide how focus moves, which keys operate it, and how state changes are exposed. Custom code transfers ongoing implementation, interoperability, and test work to your team.

3. Add ARIA only when it communicates accurate semantics

ARIA can expose roles, names, states, properties, landmarks, and status messages. It does not provide a widget’s keyboard behavior. Prefer native HTML when it offers the required control. For a custom dialog, tab set, menu, combobox, grid, or other widget, choose the relevant APG pattern, implement its focus and keyboard behavior, and test it in the browser and assistive technology combinations that matter to your users.

Keep dynamic ARIA state synchronized with the visible interface. For example, update aria-expanded when a disclosure opens or closes. An attribute that says a control is expanded while its panel is hidden exposes a false state.

<button type="button" aria-expanded="false" aria-controls="details">
  Show details
</button>
<div id="details" hidden>Additional information.</div>

<script>
  const toggle = document.querySelector('[aria-controls="details"]');
  const panel = document.getElementById('details');

  toggle.addEventListener('click', () => {
    const open = toggle.getAttribute('aria-expanded') === 'true';
    toggle.setAttribute('aria-expanded', String(!open));
    panel.hidden = open;
  });
</script>

This disclosure uses a native button, so the browser supplies its basic keyboard behavior. More complex widgets such as a tab set need their own documented key model and focus management; do not assume that adding role="tablist" creates one.

4. Make content perceivable and robust

Give non-text content a text alternative that serves the content’s purpose. If an image is informative, describe the information users need; if it is decorative, implement it so assistive technology can ignore it, such as an empty alt attribute on a decorative image. Give every control an accessible name that describes its purpose, and ensure its role and current state or value are available programmatically.

Make status messages available to assistive technology without moving focus unnecessarily. Use CSS that preserves visible focus, usable text when enlarged, and content that remains available when users adapt colors. Avoid visual reordering that conflicts with logical reading and focus order. Progressive enhancement can keep essential content and service functionality usable when CSS or JavaScript fails or is disabled.

5. Build forms with labels, instructions, and useful errors

Associate each field with a label. Use fieldset and legend when controls form a meaningful group, such as a set of related radio buttons. Explain requirements before a user makes an error, and request only information needed for the task.

<form>
  <fieldset>
    <legend>Preferred contact method</legend>
    <label><input type="radio" name="contact" value="email"> Email</label>
    <label><input type="radio" name="contact" value="phone"> Phone</label>
  </fieldset>

  <label for="postal-code">Postal code</label>
  <p id="postal-hint">Enter the code used for your billing address.</p>
  <input id="postal-code" name="postalCode" aria-describedby="postal-hint postal-error">
  <p id="postal-error">Enter a postal code.</p>
  <button type="submit">Continue</button>
</form>

When validation fails, identify the field and explain the correction in visible text, programmatically associated with the field where appropriate. Ensure important status updates are announced without a needless focus jump. WCAG 2.2 includes Name, Role, Value at Level A and Status Messages at Level AA; the WAI forms tutorial connects form practices to criteria such as Info and Relationships, Headings and Labels, and Labels or Instructions.

Avoid time limits on forms where possible. If a limit is necessary, provide a way to turn it off or extend it, except in situations where timing is essential, such as a live event or a time-sensitive submission.

6. Make keyboard access part of the feature

Ask: “Can you reach anything that’s interactive using the tab key?” Then check the whole interaction, not just whether focus lands on a control. All functionality must be available through a keyboard interface, and the focus sequence must be usable and visible.

  • Tab through links, buttons, and form controls in a logical order.
  • Use the expected keys for each control: for example, Enter or Space for buttons and arrow keys where a widget pattern calls for them.
  • Check that focus is visible, does not disappear off screen, and is not trapped in a component without a valid escape.
  • Open and close dialogs, menus, disclosures, and other dynamic UI with the keyboard, and verify focus moves and returns appropriately.
  • Check that visual layout changes do not create a confusing difference between reading order and focus order.

Custom ARIA widgets need explicitly implemented keyboard behavior. Use the APG pattern as a starting point and test the actual control in target browser and assistive technology combinations; a pattern example does not remove the need to verify your implementation.

7. Test during development, in layers

Begin with high-touch pages, critical user paths, and shared templates. Include checks throughout development instead of waiting for a final audit. Automation can help identify classes of issues, but a scan alone does not establish conformance and cannot judge every question of meaning or usability.

  1. Review structure: Check heading order, landmarks, document language, labels, names, and meaningful alternatives.
  2. Use the keyboard: Complete critical journeys using Tab and the expected arrow, Enter, and Space keys. Check visible focus, order, and escape routes.
  3. Use a screen reader: Ask, “Can you use a screen reader to access the page content?” Check that content, controls, labels, instructions, and updates are announced meaningfully.
  4. Exercise states: Test validation errors, success messages, dialogs, menus, loading states, and other dynamic interactions.
  5. Adapt presentation: Increase text size or change colors and confirm that content and controls remain usable.
  6. Check resilience: Where the architecture permits, verify essential behavior if CSS or JavaScript is unavailable.
  7. Use automated checks as one input: Record what was scanned and what still needs human or assistive technology testing.

Record the pages, user journeys, browsers, assistive technologies, and manual checks actually covered. Tie findings to the project’s applicable WCAG target. The APG recommends testing, and GOV.UK and Digital.gov provide practical manual check guidance; using a tool or a technique does not establish that the site conforms.

8. Troubleshoot common accessibility failures

Symptom Likely cause Fix
A control cannot be reached or activated by keyboard A generic element is standing in for a native control, or custom keyboard behavior is missing. Use a native link, button, or form control where possible. For a custom widget, implement and test the selected keyboard model.
Screen reader announces “button” with no useful name The control has no accessible name, or its visible text is missing from the naming relationship. Add visible text or a programmatic label that describes the action; verify the computed name in a screen reader.
Expanded state is announced incorrectly ARIA attributes were not updated when the interface changed. Update the state attribute alongside the actual UI state, and verify both open and closed states.
Form errors are visible but not discoverable to assistive technology The error is not associated with the field or announced at a useful point. Provide visible, specific error text and associate it with the control; make relevant status changes available without unnecessary focus movement.
Keyboard focus is hard to see or goes behind a panel CSS removed or obscured the focus indicator, or overlay and layout behavior was not checked. Preserve a visible focus style and check it against the actual layout, including open dialogs and sticky regions.
Automated scan passes but users still cannot complete a task The scan did not exercise the interaction or assess meaning, focus flow, or assistive technology behavior. Run the keyboard, screen reader, form-state, and critical-journey checks in the testing workflow.
A custom widget works in one browser but not another Custom semantics or interaction may be exposed differently across browser and assistive technology combinations. Prefer native controls when suitable and test the combinations relevant to users; simplify or revise the custom pattern if needed.

9. Keep the process reliable and proportionate

Accessibility work is easier to maintain when shared components carry consistent semantics, states, and focus behavior. Recheck a component when its markup, JavaScript state, or visual layout changes, and retest shared templates because one defect can affect many pages. Prioritize high-impact journeys and document limits in test coverage rather than extrapolating from a small sample.

There is no single scan, code pattern, or purchase that proves conformance. The useful output of testing is a clear account of the target, the checks performed, issues found, and untested areas. Apply the appropriate WCAG level for the project and revisit the evidence when the interface or requirements change.

10. Use screenshots to review visual states

Screenshots can help teams inspect rendered pages and compare visual states, but they cannot establish keyboard behavior, accessible names, announcements, or screen reader usability. Keep screenshot review as a visual aid alongside the interaction and assistive technology checks above.

ScreenshotNeo is a website screenshot API and MCP server for developers. Its captures accept cookie and consent banners and remove more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Responses identify page verdict and billing status, and bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits cost nothing. Its MCP server offers screenshot, page information, and PDF tools for AI agents. See the ScreenshotNeo API documentation.

Or skip the browser setup

One GET request returns a screenshot. This cURL example saves a WebP image of Stripe:

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp

The equivalent Python and Node.js requests are:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for 1,000 free screenshots a month, with no card.

11. FAQ

Does using ARIA make a custom control accessible?

No. ARIA exposes semantics and state; developers still need to implement interaction, focus behavior, and keyboard support.

Does passing an automated accessibility scan mean a site conforms to WCAG?

No. A scan can find some issue types, but conformance depends on the applicable criteria and broader evaluation, including interaction and human judgment.

Do I have to use a specific WCAG technique?

No. W3C techniques are examples, not required recipes. The implementation must still satisfy the applicable success criteria.

What should I test first?

Start with critical user paths, high-touch pages, and shared templates, then expand coverage and document what remains untested.

Primary resources