How to Fix Common Accessibility Issues (With Code Examples)
TLDR
The most common accessibility issues have straightforward fixes. Add alt attributes to images, associate labels with form inputs, ensure 4.5:1 color contrast, make all interactive elements keyboard-accessible, use proper heading hierarchy, add ARIA attributes to custom widgets, and manage focus when content changes dynamically.
- Alt Text
- The text value of an image's alt attribute in HTML. Screen readers read alt text aloud so users who cannot see the image understand what it conveys. Decorative images use an empty alt attribute (alt='') to tell screen readers to skip them.
DEFINITION
- ARIA Labels
- HTML attributes from the Accessible Rich Internet Applications specification that provide accessible names and descriptions to elements. aria-label provides an invisible text label, aria-labelledby references another element's text as the label, and aria-describedby adds supplementary description.
DEFINITION
- Focus Trap
- A situation where keyboard focus enters a component (like a modal dialog) and cannot leave using the Tab key. Focus traps violate WCAG 2.1.2 and make the page unusable for keyboard-only users. Modal dialogs should trap focus intentionally but also provide an Escape key to close.
DEFINITION
- Skip Navigation
- A link placed at the top of the page (usually visually hidden until focused) that lets keyboard users skip past the header and navigation to reach the main content directly. Without skip navigation, keyboard users must Tab through every navigation link on every page.
DEFINITION
Fixing the Issues That Matter Most
Accessibility violations cluster around the same problems across millions of websites. You do not need to memorize all 78 WCAG success criteria to make meaningful progress. Fix the seven issues covered in this guide and you address the overwhelming majority of automated scan findings and the highest-risk items in ADA enforcement.
Fix 1: Missing Alt Text on Images
Missing alt text is the most common accessibility violation on the web. Every meaningful image needs an alt attribute that describes what the image conveys.
<!-- Bad: no alt attribute -->
<img src="team-photo.jpg">
<!-- Bad: meaningless alt text -->
<img src="team-photo.jpg" alt="image">
<!-- Good: descriptive alt text -->
<img src="team-photo.jpg" alt="A11yProof engineering team in the office">
<!-- Decorative image: empty alt tells screen readers to skip it -->
<img src="decorative-divider.svg" alt="">
For functional images — icons inside buttons, linked logos — describe the function, not the image: alt="Search" for a magnifying glass icon, alt="A11yProof home" for a linked logo.
Fix 2: Low Color Contrast
WCAG requires a 4.5:1 contrast ratio for normal text and 3:1 for large text (18pt+). Common failures: light gray text on white backgrounds, white text on light-colored headers, placeholder text that barely differs from the background.
/* Bad: 2.5:1 contrast ratio */
.subtitle { color: #999999; background: #ffffff; }
/* Good: 7:1 contrast ratio */
.subtitle { color: #545454; background: #ffffff; }
Use a contrast checker (built into Chrome DevTools or standalone tools like WebAIM’s contrast checker) to verify ratios before deploying.
Fix 3: Missing Form Labels
Every form input needs a programmatically associated label. Placeholder text disappears when users start typing and is not recognized as a label by all screen readers.
<!-- Bad: placeholder only, no label -->
<input type="email" placeholder="Enter your email">
<!-- Good: visible label with for/id association -->
<label for="signup-email">Email address</label>
<input type="email" id="signup-email" placeholder="you@example.com">
<!-- Alternative: wrapping label -->
<label>
Email address
<input type="email" placeholder="you@example.com">
</label>
If your design hides labels visually, use a CSS class that hides the label from sight but keeps it available to screen readers — never use display: none or visibility: hidden on labels, as those hide them from assistive technologies too.
Fix 4: Keyboard Navigation
Every interactive element must be reachable and usable with only a keyboard. The most common failures: click handlers on <div> or <span> elements instead of <button> or <a> elements, and custom components that swallow keyboard events.
<!-- Bad: div with click handler, not keyboard accessible -->
<div onclick="submitForm()">Submit</div>
<!-- Good: button element, keyboard accessible by default -->
<button type="submit">Submit</button>
If you absolutely must use a non-semantic element, add keyboard support explicitly:
<div role="button" tabindex="0"
onclick="submitForm()"
onkeydown="if(event.key==='Enter'||event.key===' ')submitForm()">
Submit
</div>
But the better fix is almost always to use the right HTML element in the first place.
Fix 5: Heading Structure
Screen reader users navigate pages by jumping between headings. A proper heading hierarchy tells them the document structure without requiring them to read every word.
<!-- Bad: skipped heading levels, headings used for styling -->
<h1>Our Product</h1>
<h4>Features</h4> <!-- skipped h2 and h3 -->
<h2>Pricing</h2>
<!-- Good: logical heading hierarchy -->
<h1>Our Product</h1>
<h2>Features</h2>
<h3>AI Scanning</h3>
<h3>Code Fixes</h3>
<h2>Pricing</h2>
Use CSS for visual styling, not heading levels. If you want smaller text that is not a heading, use a <p> with a CSS class.
Fix 6: ARIA Attributes for Custom Widgets
Native HTML elements have built-in accessibility — a <button> announces itself as “button” to screen readers without any extra work. Custom widgets built from <div> elements have no inherent semantics. ARIA fills that gap.
<!-- Custom tab interface with ARIA -->
<div role="tablist" aria-label="Product information">
<button role="tab" aria-selected="true" aria-controls="panel-features">
Features
</button>
<button role="tab" aria-selected="false" aria-controls="panel-pricing">
Pricing
</button>
</div>
<div role="tabpanel" id="panel-features">...</div>
<div role="tabpanel" id="panel-pricing" hidden>...</div>
Important: ARIA does not add behavior, only semantics. You still need to implement keyboard navigation (arrow keys between tabs, Tab into the panel) with JavaScript.
Fix 7: Focus Management
When content changes dynamically — a modal opens, a form submits, a notification appears — keyboard focus needs to be managed explicitly.
// When opening a modal, move focus to the first focusable element
function openModal() {
const modal = document.getElementById('modal');
modal.hidden = false;
modal.querySelector('button, [href], input').focus();
}
// When closing, return focus to the trigger element
function closeModal(triggerElement) {
document.getElementById('modal').hidden = true;
triggerElement.focus();
}
For status messages that should not steal focus, use ARIA live regions:
<div aria-live="polite" aria-atomic="true">
<!-- JavaScript updates this text when status changes -->
Item added to cart
</div>
Automate What You Can
Manual fixes are essential, but you should not rely on remembering to check every page after every deployment. Tools like A11yProof automate scanning, generate specific code fixes for detected issues, and run scheduled rescans to catch regressions. Integrate accessibility testing into your build process and catch issues before they reach production.
Q&A
What are the most common accessibility issues found in automated scans?
The WebAIM Million annual analysis consistently finds the same issues: missing image alt text (SC 1.1.1), low color contrast (SC 1.4.3), empty links (SC 2.4.4), missing form labels (SC 1.3.1), missing document language (SC 3.1.1), and empty buttons (SC 4.1.2). These six issues account for the majority of automatically detectable WCAG violations. Fixing them addresses the bulk of your automated scan findings.
Q&A
Do I need to learn ARIA to fix accessibility issues?
For most fixes, no. Using proper semantic HTML — button elements for buttons, label elements for form labels, heading elements for headings — handles the majority of accessibility requirements without any ARIA. ARIA is needed only for custom interactive widgets (tabs, accordions, tree views, modals) that have no native HTML equivalent. The first rule of ARIA is: do not use ARIA if you can use a native HTML element instead.
Q&A
How do I test that my fixes actually work?
After applying fixes, run an automated scan to confirm the violations are resolved. Then test manually: Tab through the page to verify keyboard access, run a screen reader to verify labels and announcements, zoom to 200% to verify reflow. A11yProof's rescan feature lets you verify fixes immediately after deployment.
Like what you're reading?
Try A11yProof free — start scanning your site today.
Want to learn more?
How do I fix accessibility issues without breaking my design?
Should I fix all accessibility issues at once or prioritize?
Can A11yProof generate the actual code fixes for me?
What is the difference between aria-label and aria-labelledby?
How do I make a modal dialog accessible?
Keep reading
How to Audit Your Website for Accessibility (Step-by-Step)
A practical, step-by-step guide for auditing your website's accessibility. Covers automated scanning, manual testing, WCAG criteria, and how to prioritize fixes.
WCAG 2.1 AA Compliance Checklist for Website Owners
A plain-English WCAG 2.1 AA compliance checklist organized by the four POUR principles. Covers the most common success criteria and how to test them.
7 Best Web Accessibility Testing Tools (2026)
We compared 7 accessibility testing tools by scanning depth, fix generation, pricing, and real WCAG compliance capabilities. Here's which ones actually help and which ones just add a widget.
Best axe DevTools Pro Alternative for Teams Who Need a Business Dashboard
Looking for an axe DevTools Pro alternative with a business-facing dashboard and AI remediation? See how A11yProof compares for teams beyond just developers.
accessiBe Pricing in 2026: Full Cost Breakdown
What does accessiBe actually cost? We break down plans, per-site pricing, and the hidden costs of overlay-based compliance.
How to Add Accessibility Testing to Your CI/CD Pipeline
A step-by-step guide for integrating automated accessibility testing into your CI/CD pipeline using axe-core, pa11y, and other tools. Catch WCAG violations before they reach production.