A website may look correct, work well with a mouse, and display properly on different screen sizes while still being difficult for some people to use.
For example, a user who relies on a screen reader may not understand what a button does because it has no accessible name. A keyboard user may be unable to reach a menu. Someone with low vision may struggle to read text because the contrast between the text and background is too low.
These are accessibility problems, and they can affect everyday tasks such as signing in, filling out forms, navigating a menu, or completing a purchase.
Finding these issues before release is easier than fixing them after users encounter them. Developers can include accessibility checks in their normal testing process, use automated tools to identify common problems, and manually test the parts of the website that automated tools cannot fully evaluate.
This article explains how to check a website for accessibility problems using browser tools, automated testing, Playwright, and practical manual checks.
What Website Accessibility Means
Website accessibility means designing and building websites so that people with different abilities can use them.
This includes people who use screen readers, keyboard navigation, voice control, screen magnification, or other assistive technologies. It also includes people who may have temporary limitations, such as an injured hand or difficulty reading a screen in bright sunlight.
The Web Content Accessibility Guidelines (WCAG) provide widely used criteria for evaluating web accessibility. They organize requirements around four principles: content should be perceivable, operable, understandable, and robust.
In practical development work, these principles mean that users should be able to identify information, operate controls, understand what happens after an action, and use the website with supported browsers and assistive technologies.
For example, an icon-only search button may be visually clear to a sighted user but meaningless to a screen reader if it has no accessible name. A form may display an error in red, but a user who cannot distinguish the color may not realize which field needs attention.
Accessibility testing helps find these problems before they become release issues.
Start with Automated Accessibility Scans
Automated scanning is a useful first step because it can identify many common accessibility problems quickly.
Tools such as axe DevTools, Lighthouse, and other accessibility testing libraries can detect issues including missing accessible names, certain color-contrast failures, invalid ARIA attributes, and some incorrect relationships between form controls.
These tools do not understand every aspect of the user experience. A scan may pass even when a navigation menu is confusing, keyboard focus is difficult to follow, or a screen reader announces information in an unexpected order.
Treat automated results as an important source of evidence, not proof that a website is fully accessible.
Run an accessibility audit in Chrome
Open your website in Chrome and open Developer Tools.
Navigate to the Lighthouse panel, select the accessibility category, and run an audit. Review the reported problems and follow the affected elements back to the page.
Depending on the Chrome version, the available audit options and interface may differ.
Pay attention to the actual affected component rather than simply trying to increase the overall score. A missing label on a payment field may be more important to fix immediately than a minor issue on a decorative element.
Run the audit on several representative pages, including forms, navigation, search results, account settings, and any important checkout or registration flows.
A single homepage audit cannot identify problems on pages that were never tested.
Use Browser Developer Tools to Inspect Individual Elements
When an automated scan reports an issue, browser Developer Tools can help you identify the underlying HTML and CSS.
For example, inspect a button that has been reported as missing an accessible name.
This button has visible text and is generally understandable to assistive technology:
<button type="button">
Search
</button>
An icon-only button needs an accessible name:
<button type="button" aria-label="Search">
<svg aria-hidden="true" viewBox="0 0 24 24">
<circle cx="10" cy="10" r="6"></circle>
<path d="M14.5 14.5 L21 21"></path>
</svg>
</button>
The aria-label provides a name for the button, while aria-hidden="true" prevents the decorative icon from being announced separately.
For controls that already have visible text, prefer a meaningful visible label when practical. It is usually easier to maintain and helps users who may not understand an icon.
When inspecting an element, check the computed styles, accessible name, role, focus behavior, and relationships with associated labels or descriptions.
Do not add ARIA attributes simply to silence a scanner. The attributes must reflect the actual behavior of the component.
Check Keyboard Navigation
Keyboard testing is essential because automated scanners cannot reliably determine whether every interaction is usable.
Many users navigate websites with the Tab, Shift+Tab, Enter, Space, and arrow keys. Some users cannot use a mouse at all.
Open the page and complete an important user journey using only the keyboard.
For example, test whether you can:
Move through navigation links in a logical order.
Open and close menus without using a mouse.
Reach every interactive control.
Identify which element currently has focus.
Operate dialogs and close them when appropriate.
Complete and submit forms.
Escape from popups or menus without getting trapped.
A simple visual focus style helps users identify the active element.
:focus-visible {
outline: 3px solid #005fcc;
outline-offset: 3px;
}
This example provides a visible outline when the browser determines that keyboard-style focus indication is appropriate.
Check that the outline remains visible against the surrounding background and is not clipped by containers. Do not remove the browser's focus outline without providing a clear replacement.
Also test custom controls. A clickable div may respond to a mouse click but remain inaccessible to keyboard users unless its semantics and keyboard behavior are implemented correctly. Whenever possible, use native HTML elements such as buttons, links, and form controls instead of recreating their behavior manually.
Check Form Labels and Error Messages
Forms are a common source of accessibility problems because users need to understand what each field expects and how to correct invalid input.
Consider this example:
<input type="email" placeholder="Enter email">
The placeholder may disappear when the user types, and it does not replace a proper label.
A better implementation connects a visible label to the input:
<label for="email">Email address</label>
<input
id="email"
name="email"
type="email"
autocomplete="email"
required
>
The for attribute matches the input's id, allowing the label to identify the field.
Validation messages also need attention. When a user enters an invalid value, the website should explain the problem and identify the field that needs correction.
For example:
<label for="email">Email address</label>
<input
id="email"
name="email"
type="email"
aria-invalid="true"
aria-describedby="email-error"
>
<p id="email-error">
Enter a valid email address.
</p>
In a real form, set aria-invalid="true" only when the field is actually invalid, and ensure the error message is present when referenced.
Test whether users can discover errors after submission, move back to the affected fields, and understand how to fix them. If the form displays a general error summary, consider linking each message to the relevant field.
For errors that appear dynamically, check whether assistive technology users are informed appropriately. Live regions can help announce important changes, but they should not generate excessive announcements while users are typing.
Check Color Contrast and Text Readability
Text must be distinguishable from its background. Low contrast can make information difficult to read, especially for users with low vision or in poor lighting conditions.
WCAG 2.2 Level AA generally requires a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text. Large text generally means at least 18-point regular text or 14-point bold text.
Some interface components and graphical objects have separate contrast requirements.
For example, this combination may be difficult to read:
.muted-text {
color: #b8b8b8;
background-color: #ffffff;
}
A darker text color improves the contrast:
.muted-text {
color: #595959;
background-color: #ffffff;
}
Use a contrast checker or browser accessibility tool to evaluate the actual colors. Do not judge contrast based only on how the page looks on your monitor.
Also check links, disabled controls, error messages, placeholder text, and text displayed over images.
Color should not be the only way to communicate important information. For example, an invalid field should not be indicated only by a red border. Include a clear message or another visible indication of the problem.
Automate Accessibility Tests with Playwright and axe-core
Manual testing is important, but repeating every automated check before each release can be time-consuming.
Playwright can automate browser interactions, while axe-core can scan rendered pages for many common accessibility violations.
Install Playwright's test runner and the axe integration:
npm install --save-dev @playwright/test @axe-core/playwright
npx playwright install
Create a test file such as accessibility.spec.ts:
import { test, expect } from "@playwright/test";
import AxeBuilder from "@axe-core/playwright";
test("homepage has no detected WCAG 2.2 AA violations", async ({
page
}) => {
await page.goto("http://localhost:3000");
const results = await new AxeBuilder({ page })
.withTags([
"wcag2a",
"wcag2aa",
"wcag21a",
"wcag21aa",
"wcag22aa"
])
.analyze();
expect(results.violations).toEqual([]);
});
This test opens the homepage, runs an axe-core analysis against the rendered page, and fails if the scan reports violations matching the selected rule tags.
The application must be running at the configured address, and the Playwright test environment must be able to reach it.
The selected tags cover several WCAG criteria, but they do not prove complete WCAG conformance. Some accessibility requirements cannot be reliably evaluated by an automated scan.
If the test fails, inspect the reported violations and affected elements before changing the code. A rule may identify several instances of the same underlying component problem.
Test important pages, not just the homepage
A homepage test is a useful starting point, but it does not cover the rest of the application.
Create tests for representative pages and interaction states, including:
Login and registration forms.
Search results and filtering controls.
Dialogs and dropdown menus.
Checkout and payment steps.
Validation errors.
Authenticated pages and account settings.
For example, a form can appear accessible before submission but expose poorly associated error messages after invalid data is submitted.
You can also include keyboard interaction tests:
import { test, expect } from "@playwright/test";
test("search button can be reached using the keyboard", async ({
page
}) => {
await page.goto("http://localhost:3000");
const searchButton = page.getByRole("button", {
name: "Search"
});
await page.keyboard.press("Tab");
await expect(searchButton).toBeFocused();
});
This example assumes the search button is the first focusable element reached by Tab on the page. If the page has other focusable elements before it, adjust the test to match the expected navigation order.
The goal is not merely to prove that a button exists. It is to verify that users can reach and operate it in the intended sequence.
Integrate Accessibility Checks into CI/CD
Accessibility tests are most useful when they run regularly rather than only before a major release.
Add the automated tests to your continuous integration pipeline so they execute when developers create pull requests or merge changes.
A typical workflow includes installing dependencies, building the application, starting the test environment, and running Playwright tests.
For example:
npm ci
npx playwright install --with-deps
npm run build
npx playwright test
The exact commands depend on your project. Some applications need a separate command to start the development server or preview server before the tests can run.
When an accessibility test fails, provide the affected page, violation details, and relevant test output so developers can investigate the issue quickly.
Avoid treating every automated warning as equally important. Prioritize problems that prevent users from completing essential tasks, while still tracking other violations and fixing them systematically.
It is also useful to run tests with different viewport sizes and, where practical, different browsers. Responsive layouts can introduce focus, clipping, and readability problems that do not appear at a single screen size.
Understand What Automated Tools Cannot Find
Automated tools can detect many technical issues, but accessibility also depends on whether the experience makes sense to real users.
A page can pass an axe-core scan and still have confusing instructions, an illogical heading structure, an awkward keyboard flow, or a dialog that is difficult to understand with a screen reader.
Before release, combine automated scans with manual testing.
Review the page using keyboard navigation, inspect accessible names and roles, check zoom and reflow behavior, and test important flows with appropriate assistive technologies.
For critical user journeys, consider usability testing with people who use assistive technology. Their feedback can reveal problems that are difficult to predict from code alone.
Also distinguish between conformance testing and usability testing. A site can satisfy specific technical criteria while still offering an unnecessarily difficult experience.
Common Accessibility Testing Mistakes
One mistake is relying entirely on Lighthouse or another automated score. A score is a useful signal, but it does not represent every accessibility requirement.
Another is fixing individual warnings without addressing the shared component responsible for them. If every page uses the same inaccessible button component, fixing that component may resolve many issues at once.
Developers should also avoid adding ARIA attributes without understanding their effects. Incorrect roles, labels, or live-region behavior can make a component harder to use.
Finally, do not leave accessibility testing until the final day of a release. Integrating checks into development and code review makes problems easier to identify while the implementation is still fresh.
Conclusion
Finding accessibility problems before release requires a combination of automated scanning, keyboard testing, form validation checks, and manual review.
Start with browser tools to identify common issues, use Developer Tools to inspect the affected elements, and add Playwright tests with axe-core to catch regressions automatically.
Then test important user journeys manually, including navigation, forms, dialogs, and error handling. Automated tools can identify many technical problems, but they cannot confirm that every interaction is understandable and usable.
Making accessibility checks part of the normal development process helps teams identify problems earlier, reduce repeated fixes, and deliver websites that work for more people.
Join the conversation! Your thoughts help the community grow.