CodeChallenge LogoCodeChallenge

The 5 Most Common HTML Accessibility Bugs That Fail WCAG Audits

Most accessibility failures are not design problems — they are missing labels, invisible focus outlines, keyboard traps, low contrast, and icon buttons without text alternatives.

July 27, 2026
6 min read
#accessibility #html #wcag #a11y #frontend
The 5 Most Common HTML Accessibility Bugs That Fail WCAG Audits

I once worked on a dashboard that scored 99 on Lighthouse accessibility. The product manager was proud. Then a blind user emailed us saying they could not complete the checkout flow. The form had perfectly labeled inputs and proper ARIA attributes — but the modal that appeared after submitting had no focus management. Tab pressed inside the modal cycled through elements behind it. The user could not see the confirmation message and assumed the purchase failed.

That experience taught me that accessibility is not about hitting a score. It is about catching the five bugs that block real users every day. These five failures account for roughly 80 percent of WCAG audit failures, and each one takes less than five minutes to fix once you know what to look for.

1. Missing Focus Indicator

The first bug is the easiest to spot once you know where to look. When you tab through a page using your keyboard, the browser draws a visible ring around the currently focused element. Many developers remove this ring with outline: none to make the design look cleaner, then forget to provide an alternative. Keyboard users rely entirely on that ring to know where they are on the page. Without it, they cannot navigate forms, menus, or links. Try tabbing through the two buttons below to see the difference.

The fix is simple. Use :focus-visible instead of :focus so the ring appears only for keyboard users, not for mouse clicks. Pick a color that contrasts with your background — yellow or blue works well on most surfaces — and set a clear outline or box-shadow so the focused element is unmistakable. Do not rely on the browser default if it does not match your design, but never remove the ring without replacing it.

/* Problem */
button:focus { outline: none; }

/* Fix */
button:focus-visible {
  outline: 2px solid #FFC832;
  outline-offset: 2px;
}

That is the simplest fix on this list. The next bug is more insidious because it does not break visually. It only breaks for keyboard users, and you will not notice it unless you test with Tab.

2. Keyboard Traps

A keyboard trap happens when focus enters a component — like a modal, a dialog, or an embedded widget — and cannot leave using Tab or Shift+Tab. The user presses Tab repeatedly and the focus cycles inside the component but never returns to the main page. The only way out is to close the browser tab. Try the two modals below. The first one traps you. The second one lets you press Esc to leave.

Every modal must implement a focus trap: when Tab is pressed on the last focusable element, focus jumps back to the first. When Shift+Tab is pressed on the first, focus jumps to the last. And Escape must close the modal and return focus to the element that triggered it. I have fixed this bug in production at least four times. It is easy to overlook because sighted developers tab through a modal once, see it works, and ship it. The bug only appears when the modal has enough elements to wrap the focus cycle, which happens at different points depending on the content.

// Trap Tab inside modal
document.addEventListener('keydown', (e) => {
  if (e.key === 'Escape') {
    closeModal()
    triggerButton.focus()
  }
})

Keyboard traps affect users who cannot use a mouse. The next bug affects everyone who uses a screen reader, even if they can see the screen perfectly.

3. Icon-Only Buttons Without Labels

A close button with only an X icon looks clean, but screen readers see <button> with no text. The user has no idea what the button does. The same applies to hamburger menus, search icons, and any button where the visual label is purely graphical. Compare the two buttons below. They look identical, but one tells a screen reader what it does.

The fix is to add aria-label to every icon-only button. The label should describe the action, not the icon: “Close dialog” instead of “X”, “Open menu” instead of “hamburger.” If the button has visible text, you do not need aria-label. But if the only visual content is an icon or symbol, always provide a text alternative.

Code
<!-- Problem: screen reader hears "button" -->
<button><span class="icon-x"></span></button>

<!-- Fix: screen reader hears "Close dialog button" -->
<button aria-label="Close dialog">
  <span class="icon-x"></span>
</button>

Screen reader users rely on text labels. The next bug affects people with low vision — they can see the screen but cannot read low-contrast text.

4. Insufficient Color Contrast

Light gray text on a white background looks minimal and modern. It also fails WCAG 1.4.3, which requires a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text. Users with low vision or color blindness simply cannot read low-contrast text. The two samples below show the same message with different contrast levels.

The fix is to check your color combinations before shipping. I use the browser devtools color picker — it shows the contrast ratio as you pick colors. If the ratio is below 4.5, darken the text or lighten the background until it passes. Common offenders are placeholder text, secondary labels, disabled buttons, and footer links. These are often styled with light colors that look fine to a designer but fail the ratio test. Darken them by one shade and test again.

Code
/* Problem: contrast ratio 2.8:1 */
.muted-text { color: #9CA3AF; }

/* Fix: contrast ratio 6.5:1 */
.muted-text { color: #374151; }

Color contrast affects readability. The last bug on this list is about form fields that look labeled but lose their labels the moment you start typing.

5. Form Inputs Without Labels

Relying on a placeholder as the only label is the most common form accessibility bug. Placeholder text disappears when the user starts typing. If the user forgets what the field is for, they have to clear the input to see the hint again. Screen readers may skip placeholder text entirely. Try the two inputs below — type something in each and see which one still tells you what the field is for.

Always use a <label> element associated with the input via the for attribute. The placeholder can remain as a hint about format, but it should never be the sole identifier of the field. A proper label stays visible at all times and works with all assistive technologies.

Code
<!-- Problem: placeholder disappears on input -->
<input type="email" placeholder="Enter your email" />

<!-- Fix: label stays visible -->
<label for="email">Email address</label>
<input id="email" type="email" placeholder="you@example.com" />

How to Test for These Bugs

Testing for accessibility does not require expensive tools or expert knowledge. Before shipping any page, tab through every interactive element using only the keyboard. Can you see where you are at every step? Can you open and close every modal? Can you complete every form? If the answer to any of these is no, you have found one of these five bugs.

Browser devtools can check contrast ratios immediately. The Lighthouse tab in Chrome DevTools runs an automated accessibility audit that catches most of these issues. And screen reader testing with a free tool like NVDA on Windows or VoiceOver on Mac reveals problems that automated tools miss. A five-minute manual test before every deploy prevents months of accumulated accessibility debt.

Share:
Found this helpful?