DEV Community

Samcorp
Samcorp

Posted on

Our Accessibility Audit Found 340 Issues Here's the Pattern

We expected the accessibility audit to produce a long list of unrelated problems.

Our Accessibility Audit Found 340 Issues Here's the Pattern

It found 340 issues.

But the interesting part was not the number.

It was the pattern.

A small group of recurring mistakes accounted for most of the failures.

340 findings
     ↓
A handful of repeated patterns
     ↓
A much smaller number of root causes
Enter fullscreen mode Exit fullscreen mode

That changed how we approached the fixes.

Instead of repairing 340 problems individually, we started fixing the components and design decisions creating them.

Note: The counts in this post are representative examples based on a typical mixed automated/manual audit. Replace them with your actual audit results before presenting them as project data.


What the Audit Found

We grouped the 340 findings by root cause.

Issue Type Findings Share
Color contrast 112 32.9%
Form labels 63 18.5%
Image alternative text 49 14.4%
Keyboard and focus 38 11.2%
Links and button names 31 9.1%
Heading and page structure 27 7.9%
Other issues 20 5.9%
Total 340 100%

The distribution surprised us.

Nearly two-thirds of the findings came from just three areas:

Contrast
+
Forms
+
Images
Enter fullscreen mode Exit fullscreen mode

This was not unusual.

The 2026 WebAIM Million study found low-contrast text on 83.9% of analyzed home pages, missing image alternative text on 53.1%, and missing form labels on 51%. WebAIM also found that six common error types represented 96% of all automatically detected errors.

Our audit reinforced the same lesson:

Accessibility problems often repeat because the underlying implementation repeats.


Pattern #1: Contrast Problems Were Mostly Design-System Problems

The largest category contained 112 findings.

At first they looked like individual color mistakes.

.card-description {
  color: #a6a6a6;
  background: #ffffff;
}
Enter fullscreen mode Exit fullscreen mode

But the same colors appeared across cards, tables, helper text, placeholders, secondary buttons, and empty states.

Fixing every page individually would have been the wrong approach.

The real problem lived in the design tokens.

Instead of changing dozens of components, we changed the shared semantic color definitions and then retested the components that depended on them.

Fixing shared components and design tokens is also part of building scalable web platforms, because one accessible component can improve dozens of pages at once.

The lesson was:

When the same accessibility issue appears everywhere, look for the shared system creating it.

WCAG 2.2 includes minimum contrast requirements for text as well as requirements for visual information used to identify interface components and states.


Pattern #2: Forms Looked Labeled but Were Not Programmatically Labeled

The next 63 findings involved forms.

Visually, many fields looked perfectly understandable:

Email Address
[________________]
Enter fullscreen mode Exit fullscreen mode

But some implementations were closer to:

<span>Email Address</span>
<input type="email">
Enter fullscreen mode Exit fullscreen mode

A sighted user could understand the relationship.

Assistive technology could not necessarily determine it.

We replaced patterns like that with explicit labels:

<label for="email">Email Address</label>
<input id="email" type="email">
Enter fullscreen mode Exit fullscreen mode

Icon-only controls needed accessible names too:

<button aria-label="Clear search">
  <svg aria-hidden="true">...</svg>
</button>
Enter fullscreen mode Exit fullscreen mode

This category taught us that accessibility cannot be judged from screenshots alone.

The visual interface and the accessibility tree are different representations of the same product.

WCAG's Name, Role, Value requirement exists so user interface components can expose information that assistive technologies can understand.


Pattern #3: alt Text Was Not Just Missing — It Was Often Wrong

We found 49 image-related issues.

Some images had no alt attribute.

Others technically had one but used values like:

<img src="chart.png" alt="image">
Enter fullscreen mode Exit fullscreen mode

or:

<img src="team-photo.jpg" alt="team-photo.jpg">
Enter fullscreen mode Exit fullscreen mode

Those technically contain text.

They do not necessarily communicate anything useful.

We started classifying images by purpose.

Informative images received meaningful descriptions.

Decorative images used:

alt=""
Enter fullscreen mode Exit fullscreen mode

Functional images needed text that described the action or destination rather than simply describing how the image looked.

This distinction mattered more than simply asking:

Does every image have an alt attribute?

The better question was:

Does the text alternative provide the information this image contributes?

WebAIM's 2026 analysis found that 16.2% of images on the million home pages lacked alternative text, and it also identified large numbers of questionable or repetitive alternative text.


Pattern #4: Mouse Testing Hid Keyboard Problems

Thirty-eight findings appeared only when we stopped using the mouse.

We pressed Tab.

Suddenly we found:

Dropdowns that could not be opened

Dialogs that trapped focus

Clickable divs that keyboard users could not activate

Focus indicators that disappeared

Focus moving somewhere unexpected
Enter fullscreen mode Exit fullscreen mode

One common anti-pattern looked like this:

<div onclick="openMenu()">
  Menu
</div>
Enter fullscreen mode Exit fullscreen mode

The better solution was often simply:

<button type="button" onclick="openMenu()">
  Menu
</button>
Enter fullscreen mode Exit fullscreen mode

Native HTML already provides keyboard behavior, semantics, and focus support.

We had occasionally rebuilt those features ourselves and produced worse results.

WCAG 2.2 requires functionality to be operable through a keyboard, and its Focus Visible criterion requires users to be able to see where keyboard focus currently is.


Pattern #5: Icon Buttons Were Easy to See but Hard to Understand

Thirty-one findings involved empty links, empty buttons, or controls without useful accessible names.

Our interfaces contained many controls like:

<button>
  <svg>...</svg>
</button>
Enter fullscreen mode Exit fullscreen mode

A sighted user saw a trash icon.

A screen reader could encounter an unnamed button.

The fix might be:

<button aria-label="Delete project">
  <svg aria-hidden="true">...</svg>
</button>
Enter fullscreen mode Exit fullscreen mode

But the larger lesson was not “add ARIA everywhere.”

It was:

Every interactive control needs a meaningful name.

Where native visible text could do the job, we preferred that.

ARIA was useful when the visual design genuinely required an icon-only control.


Pattern #6: Heading Problems Came From Styling Decisions

We found 27 structural issues.

Some pages jumped from:

H1
 ↓
H3
 ↓
H5
Enter fullscreen mode Exit fullscreen mode

because developers chose heading elements based on their default visual size.

That is backwards.

We changed the approach:

<h2 class="small-heading">
  Account Settings
</h2>
Enter fullscreen mode Exit fullscreen mode

instead of choosing <h4> simply because it visually looked smaller.

CSS controls appearance.

HTML should describe structure.

This matters because headings are an important navigation mechanism for screen-reader users. The 2026 WebAIM study found skipped heading levels on 41.8% of analyzed home pages.


The Most Important Finding Was Duplication

Once we grouped the 340 issues, something became obvious.

Many findings were not 340 separate bugs.

For example:

21 contrast issues
→ one incorrect text token

17 missing labels
→ one shared form component

12 unnamed buttons
→ one icon-button component

9 focus problems
→ one modal implementation
Enter fullscreen mode Exit fullscreen mode

Suddenly the remediation strategy changed.

Instead of:

Find issue
   ↓
Fix page
   ↓
Find next issue
Enter fullscreen mode Exit fullscreen mode

we moved toward:

Find pattern
   ↓
Find shared component
   ↓
Fix root cause
   ↓
Regression test
   ↓
Remove many findings at once
Enter fullscreen mode Exit fullscreen mode

That was the real value of the accessibility audit.

It showed us where accessibility debt was being generated.


Automated Testing Was Useful — but It Was Not the Audit

Automated tools found many obvious problems quickly:

Contrast

Missing labels

Missing alt attributes

Empty links

Empty buttons

Some ARIA problems
Enter fullscreen mode Exit fullscreen mode

But automation could not answer every important question.

It could not reliably tell us whether:

The keyboard flow made sense

Alternative text was actually useful

A modal announced itself correctly

Focus moved to the right place

Error messages were understandable

A workflow was usable with a screen reader
Enter fullscreen mode Exit fullscreen mode

That is why our audit combined automated checks with keyboard testing and manual review.

WebAIM makes the same limitation explicit: automated tools detect only a subset of accessibility failures, and having zero automatically detected errors does not prove that a page conforms to WCAG.


What We Changed After the Audit

The biggest improvement was not fixing those 340 findings.

It was changing how new findings were prevented.

Accessibility checks moved earlier into:

Design
   ↓
Component development
   ↓
Code review
   ↓
Automated testing
   ↓
Manual keyboard testing
   ↓
Release
Enter fullscreen mode Exit fullscreen mode

Shared components became particularly important.

If we could make one button, form field, dialog, or navigation component accessible by default, dozens of future screens benefited automatically.

Accessibility stopped being something we checked at the end.

We started treating accessible UI/UX design as part of the product system itself, so contrast, component behavior, hierarchy, and WCAG requirements were considered before development reached QA.

It became part of how the component system was built.


The Data Changed Our Priorities

Before the audit, accessibility felt like a huge collection of rules.

After grouping the findings, the work became more concrete.

We did not need to solve every possible accessibility problem simultaneously.

We needed to stop repeatedly shipping the same problems.

The data showed where to start:

Fix contrast tokens.

Fix form components.

Fix image handling.

Fix keyboard interaction.

Fix accessible names.

Fix document structure.
Enter fullscreen mode Exit fullscreen mode

That was much more actionable than saying:

Make the website accessible.


The Biggest Lesson

The most useful number from the audit was not:

340 issues
Enter fullscreen mode Exit fullscreen mode

It was:

A few patterns created most of them.
Enter fullscreen mode Exit fullscreen mode

That changes accessibility work from an endless cleanup exercise into an engineering problem.

If one component creates 25 failures, fix the component.

If one design token creates 40 contrast problems, fix the token.

If one modal pattern breaks keyboard navigation across the application, fix the pattern.

Accessibility scales when the correct behavior becomes the default behavior.


Final Takeaway

An accessibility audit should not finish with a spreadsheet containing hundreds of rows.

That spreadsheet is the beginning.

Group the findings.

Look for repetition.

Trace repeated failures back to shared components, design tokens, and engineering conventions.

Then fix the systems creating the issues.

Our 340 findings looked overwhelming at first.

Once we analyzed the data, the problem became much simpler:

We did not have 340 independent accessibility problems. We had a small number of accessibility patterns repeated across the product.

And repeated problems are exactly the kind of thing engineering systems are good at fixing.

Top comments (0)