PageAudit
Back to blog

How to Fix the 7 Most Common WCAG Errors (With Code Examples)

·PageAuditors Team

Want to check your own site? Our free scanner takes 30 seconds.

Scan Your Website for Accessibility Issues

How to Fix the 7 Most Common WCAG Errors (With Code Examples)

96% of websites fail WCAG compliance. If you have ever run an accessibility scan and felt overwhelmed by the results, you are not alone. The good news: a small number of error types account for the vast majority of violations, and most of them are straightforward to fix.

We analyzed scan data from thousands of pages checked through PageAuditors and identified the seven WCAG violations that appear most frequently. This guide shows you exactly what each error means, why it matters, and how to fix it with real code examples. Each section includes the exact error message you will see in automated scanners, step-by-step fix instructions, and before-and-after code.

1. Insufficient Color Contrast (WCAG 1.4.3)

The most common violation we find. Color contrast failures appear on nearly every website we scan. The rule is simple: text must have enough contrast against its background so that people with low vision or color blindness can read it.

The Standard

WCAG 1.4.3 "Contrast (Minimum)" requires:

  • Normal text: contrast ratio of at least 4.5:1
  • Large text (18pt / 24px, or 14pt / 18.66px if bold): contrast ratio of at least 3:1

This is a Level AA requirement, meaning it is part of the baseline that courts and regulators expect you to meet.

Before (Failing)

<p style="color: #999999; background-color: #ffffff;">
  This light gray text on white has a contrast ratio of 2.85:1
</p>

<a href="/pricing" style="color: #7ab8f5;">
  View pricing
</a>

After (Passing)

<p style="color: #595959; background-color: #ffffff;">
  This darker gray on white has a contrast ratio of 7:1
</p>

<a href="/pricing" style="color: #2563eb;">
  View pricing
</a>

How to Fix It

  1. Use a contrast checker tool to test your color combinations
  2. Update your CSS color values to meet the 4.5:1 ratio for body text
  3. Pay special attention to placeholder text, disabled states, and links, which designers often style with low contrast
  4. If your brand colors fail contrast, adjust the shade slightly rather than changing the brand entirely

Common trap: Gray text on white backgrounds. Designers love light gray for a "clean" look, but #999 on #fff fails at 2.85:1. Bump it to #595959 or darker.

What PageAudit shows you: The scanner flags each failing element with the rule color-contrast and tells you the current contrast ratio. It highlights the exact text element on the page so you can see which color combination needs updating. The PageAudit Chrome extension can check any page instantly without leaving your browser.

2. Links Without Discernible Text (WCAG 2.4.4)

Links that have no accessible name are invisible to screen reader users. This happens most often with icon-only links, image links missing alt text, and empty anchor tags.

The Standard

WCAG 2.4.4 "Link Purpose (In Context)" is a Level A requirement. Every link must have text that describes where it goes, either through visible text, an aria-label, or alt text on a linked image.

Before (Failing)

<!-- Icon-only link with no text -->
<a href="/settings">
  <svg class="icon-gear" />
</a>

<!-- Image link with no alt -->
<a href="https://twitter.com/pageauditors">
  <img src="/twitter-icon.png" />
</a>

<!-- Empty link -->
<a href="/dashboard"></a>

After (Passing)

<!-- Add aria-label for icon-only links -->
<a href="/settings" aria-label="Settings">
  <svg class="icon-gear" aria-hidden="true" />
</a>

<!-- Add alt text to linked images -->
<a href="https://twitter.com/pageauditors">
  <img src="/twitter-icon.png" alt="PageAuditors on Twitter" />
</a>

<!-- Add visible or screen-reader text -->
<a href="/dashboard">
  <span class="sr-only">Go to dashboard</span>
</a>

How to Fix It

  1. Search your HTML for <a> tags that contain only icons, images, or are empty
  2. Add aria-label to icon-only links (and aria-hidden="true" on the decorative icon)
  3. Add meaningful alt text to any <img> inside a link
  4. Use a .sr-only CSS class (visually hidden, screen-reader accessible) when you need invisible text

What PageAudit shows you: The scanner flags these as link-name violations and highlights the empty or icon-only link directly on the page. Each violation includes a plain-English explanation of what is missing and how to fix it.

3. Small Touch Targets (WCAG 2.5.8)

Buttons and links that are too small to tap reliably affect everyone, but especially users with motor impairments, tremors, or who use assistive pointing devices. This is a newer criterion added in WCAG 2.2.

The Standard

WCAG 2.5.8 "Target Size (Minimum)" requires interactive elements to be at least 24 by 24 CSS pixels, or to have sufficient spacing from adjacent targets. This is Level AA in WCAG 2.2 (released October 2023).

While courts currently reference WCAG 2.1 AA for legal compliance, WCAG 2.2 criteria are increasingly cited in accessibility audits and will likely become the new baseline.

Before (Failing)

.inline-link {
  /* Small text link with no padding */
  font-size: 12px;
  padding: 0;
}

.icon-button {
  width: 16px;
  height: 16px;
}

After (Passing)

.inline-link {
  font-size: 12px;
  padding: 6px 0; /* Increases clickable area to 24px+ height */
  display: inline-block;
}

.icon-button {
  width: 24px;
  height: 24px;
  min-width: 24px;
  min-height: 24px;
}

How to Fix It

  1. Set min-width and min-height of 24px on all interactive elements (buttons, links, inputs)
  2. For inline text links, add vertical padding to expand the clickable area
  3. Ensure spacing between adjacent targets is sufficient (if you cannot make the target 24px, leave at least 24px of gap between it and neighboring interactive elements)
  4. Navigation menus and footer link lists are the most common offenders

What PageAudit shows you: Touch target violations appear as target-size flags. The scanner identifies each undersized button or link and shows its current dimensions so you know exactly how much padding to add.

4. Images Missing Alt Text (WCAG 1.1.1)

Missing alt text is the classic accessibility violation, and it is still one of the most frequent. Every meaningful image needs alternative text so screen readers can describe it. Without it, users hear nothing or hear the raw filename.

The Standard

WCAG 1.1.1 "Non-text Content" is a Level A requirement. Every <img> element must have an alt attribute. Meaningful images need descriptive text. Decorative images need an empty alt="" so screen readers skip them.

Before (Failing)

<!-- No alt attribute at all -->
<img src="/team-photo.jpg" />

<!-- Alt with just the filename -->
<img src="/hero-banner.png" alt="hero-banner.png" />

<!-- Decorative image missing empty alt -->
<img src="/divider-line.svg" />

After (Passing)

<!-- Descriptive alt for meaningful images -->
<img src="/team-photo.jpg" alt="The PageAuditors team at our New York office" />

<!-- Descriptive, not filename-based -->
<img src="/hero-banner.png" alt="Website accessibility scanner showing a compliance score of 94" />

<!-- Empty alt for decorative images -->
<img src="/divider-line.svg" alt="" />

How to Fix It

  1. Run a scan to find every <img> missing an alt attribute
  2. For each meaningful image, write alt text that describes what the image communicates (not what it looks like)
  3. For decorative images (dividers, background shapes, spacers), add alt=""
  4. Avoid generic alt text like "image," "photo," or "icon." Be specific.
  5. Keep alt text under 125 characters. For complex images (charts, infographics), use a longer description via aria-describedby

What PageAudit shows you: These appear as image-alt violations. The scanner highlights each image missing alt text and shows its src path so you can identify which image needs a description. If your page has many images, sort by severity to fix meaningful images first (decorative images just need alt="").

5. Missing Page Language (WCAG 3.1.1)

This is the easiest fix on the list and one of the most commonly missed. Without a lang attribute on the <html> element, screen readers do not know what language to use for pronunciation. A French screen reader trying to read English text (or vice versa) produces gibberish.

The Standard

WCAG 3.1.1 "Language of Page" is a Level A requirement. The <html> element must declare the primary language of the page using a valid language code.

Before (Failing)

<!DOCTYPE html>
<html>
  <head>
    <title>My Website</title>
  </head>
</html>

After (Passing)

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>My Website</title>
  </head>
</html>

How to Fix It

  1. Add lang="en" (or the appropriate language code) to your <html> tag
  2. If you use a framework like Next.js, check your root layout or _document file
  3. For multilingual sites, set the lang attribute dynamically based on the current locale
  4. This is a one-line fix that affects your entire site

In Next.js App Router:

// src/app/layout.tsx
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  );
}

What PageAudit shows you: This appears as an html-has-lang violation at the page level. It is one of the simplest flags to resolve since it requires a single attribute on your root element.

6. Heading Order Violations (WCAG 1.3.1)

Skipped heading levels are one of the most common structural errors on the web. When headings jump from <h1> to <h3> (skipping <h2>), the page loses its logical outline. Screen reader users navigate by heading level the way sighted users scan a table of contents. Skipping levels makes it impossible to understand the page structure.

The Standard

WCAG 1.3.1 "Info and Relationships" (Level A) requires that the structure of content is programmatically determinable. For headings, this means they should follow a logical, descending order without skipping levels. Every page should have exactly one <h1>, followed by <h2> sections, then <h3> subsections within those, and so on.

The Error Message

Automated scanners flag this as "Heading levels should only increase by one" (axe-core rule: heading-order). You will also see a related flag, "Page should contain a level-one heading" (page-has-heading-one), if your page is missing an <h1> entirely.

Before (Failing)

<h1>Our Services</h1>
<h3>Web Development</h3>     <!-- Skipped h2! -->
<h3>Mobile Apps</h3>
<h5>iOS Development</h5>     <!-- Skipped h4! -->
<h2>Contact Us</h2>

<!-- Common in WordPress/CMS sites: -->
<h1>Blog Post Title</h1>
<h4>Introduction</h4>        <!-- Should be h2 -->

After (Passing)

<h1>Our Services</h1>
<h2>Web Development</h2>
<h2>Mobile Apps</h2>
<h3>iOS Development</h3>
<h2>Contact Us</h2>

<!-- Correct hierarchy: -->
<h1>Blog Post Title</h1>
<h2>Introduction</h2>

How to Fix It

  1. Map out your page's heading structure like an outline. Each <h2> is a major section, each <h3> is a subsection within that <h2>, and so on
  2. Never choose a heading level for its visual size. Use CSS to control font size independently of the heading tag
  3. Ensure every page has exactly one <h1> that describes the page's main topic
  4. In CMS-driven sites, check your theme templates. Many WordPress themes use <h3> or <h4> for widget titles when <h2> would be correct
  5. For card layouts, use the appropriate level based on where the card sits in the page hierarchy, not based on how big the text should look
/* Control visual size with CSS, not heading level */
h2 {
  font-size: 1.5rem;  /* Normal h2 size */
}
h2.small-heading {
  font-size: 1rem;    /* Looks smaller, but keeps correct hierarchy */
}

Common trap: Developers pick heading levels based on visual appearance. An <h4> looks like the right size for a sidebar title, so they use <h4> even though the sidebar sits directly under the <h1>. Use CSS for styling, HTML for structure.

What PageAudit shows you: The scanner flags heading-order violations and tells you exactly which heading level was expected versus what it found (for example, "Heading level jumped from h1 to h3"). It also flags page-has-heading-one if your page is missing a top-level heading entirely. The PageAudit Chrome extension highlights the offending heading element so you can find it quickly.

7. Form Inputs Missing Labels (WCAG 1.3.1 / 4.1.2)

Form fields without labels are a major barrier for screen reader and voice control users. When a user tabs to an unlabeled text input, their screen reader announces "edit text" with no indication of what to type. Voice control users who say "click email" get no response because the field has no programmatic name.

According to WebAIM's annual survey, missing form labels appear on nearly half of all websites tested.

The Standard

WCAG 1.3.1 "Info and Relationships" (Level A) requires that form labels are programmatically associated with their inputs. WCAG 4.1.2 "Name, Role, Value" (Level A) requires that all user interface components have an accessible name. Together, these rules mean every form field needs a label that assistive technology can read.

The Error Message

Automated scanners flag this as "Form elements must have labels" (axe-core rule: label). You may also see "Multiple form labels" (form-field-multiple-labels) if a single field has more than one <label> pointing to it.

Before (Failing)

<!-- Placeholder is not a label -->
<input type="email" placeholder="Enter your email" />

<!-- Label exists but is not linked to the input -->
<label>Username</label>
<input type="text" id="username" />

<!-- No label at all -->
<div class="form-group">
  <input type="text" class="search-box" />
  <button>Search</button>
</div>

After (Passing)

<!-- Option 1: Explicit label with matching "for" and "id" -->
<label for="email">Email address</label>
<input type="email" id="email" placeholder="you@example.com" />

<!-- Option 2: Implicit label wrapping the input -->
<label>
  Username
  <input type="text" id="username" />
</label>

<!-- Option 3: aria-label for visually hidden labels -->
<div class="form-group">
  <input type="text" class="search-box" aria-label="Search the site" />
  <button>Search</button>
</div>

How to Fix It

  1. Use explicit labels whenever possible. Add a <label> element with a for attribute that matches the input's id. This is the most reliable method across all assistive technologies
  2. Never rely on placeholder text as a label. Placeholders disappear when users start typing, leaving no context. They also have low contrast by default, failing WCAG 1.4.3
  3. For search boxes and simple single-field forms, use aria-label to provide a visually hidden label. This keeps the design clean while remaining accessible
  4. Check that each label links to exactly one field. Duplicate labels (two <label> elements pointing to the same id) confuse screen readers
  5. In React/Preact, use htmlFor instead of for on label elements
{/* React/Preact: use htmlFor, not for */}
<label htmlFor="phone">Phone number</label>
<input type="tel" id="phone" />

Common trap: CSS frameworks that style inputs with floating labels sometimes remove or disconnect the actual <label> element. The visual animation looks like a label, but the HTML link is broken. Always verify with a screen reader or automated scanner that the label is programmatically associated, not just visually adjacent.

What PageAudit shows you: These appear as label violations. The scanner identifies each unlabeled form input and highlights it on the page. The fix guidance explains exactly which labeling method to use. If you have multiple labels on one field, you will see a separate form-field-multiple-labels flag.

What to Do Next

These seven errors account for the majority of WCAG violations on most websites. Fixing them does not require a complete redesign. It requires knowing where the problems are and making targeted changes.

Here is a practical approach:

  1. Scan your site to get a complete list of violations with their exact locations
  2. Fix critical and serious issues first (missing alt text, contrast failures, missing link text)
  3. Re-scan after each batch of fixes to verify the changes worked and catch any regressions
  4. Set up recurring scans to catch new violations as your site changes

Every violation you fix is one fewer risk in an ADA lawsuit and one more user who can actually use your website. And because most WCAG failures overlap with technical SEO issues, every fix also improves how Google parses and ranks your page. For the full story on that overlap, see our guide on how web accessibility improves SEO.

Run a Free Scan Now

Want to see exactly which of these errors appear on your site? You have two options:

  • PageAudit Chrome Extension: Install once, scan any page with one click. No signup, no data sent to servers. Results appear right in the browser.
  • PageAuditors Web Scanner: Enter a URL and get a full report. Scans against WCAG 2.1 AA and 2.2 criteria with plain-English fix guidance.

No signup required for either option. Results in under 30 seconds.

Frequently Asked Questions

What are the most common WCAG errors?
Based on real scan data from PageAuditors, the seven most common WCAG errors are: insufficient color contrast (WCAG 1.4.3), missing link text (WCAG 2.4.4), small touch targets (WCAG 2.5.8), missing image alt text (WCAG 1.1.1), missing page language (WCAG 3.1.1), heading order violations (WCAG 1.3.1), and form inputs missing labels (WCAG 1.3.1). Color contrast alone accounts for more violations than any other single rule.
How do I check if my website has WCAG errors?
Run a free automated scan at PageAuditors or install the free PageAudit Chrome extension for instant results. Both check your pages against WCAG 2.1 AA and 2.2 criteria, highlight every violation with its exact location in the page, and provide plain-English guidance on how to fix it. No signup required.
Which WCAG version do I need to comply with for ADA?
For ADA compliance, courts and the DOJ reference WCAG 2.1 Level AA as the technical standard. WCAG 2.2 (released October 2023) adds additional criteria but is not yet required by law. Meeting WCAG 2.1 AA is the safe baseline for legal compliance.
Can automated tools find all WCAG errors?
Automated scanners can detect 30-57% of WCAG violations, including the seven most common errors covered in this guide. The remaining issues require manual testing, such as verifying that form error messages are clear or that keyboard navigation order makes sense. Automated scanning catches the highest-volume issues first.
How long does it take to fix common WCAG errors?
Most of the errors in this guide take minutes to fix once you know what to change. Adding a lang attribute is a one-line change. Fixing color contrast requires updating CSS values. Adding alt text, link labels, form labels, and heading order takes a few minutes per element. The hardest part is finding the violations, which is why automated scanning saves hours of manual review.
How do I fix alt text on images for accessibility?
Every meaningful image needs an alt attribute that describes what the image communicates, not just what it looks like. Use alt text under 125 characters. For decorative images like dividers or background shapes, use an empty alt attribute (alt=""). Avoid generic text like 'image' or 'photo.' Run an automated scan to find every image missing alt text on your site.
How do I fix color contrast for accessibility?
WCAG requires a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text (18px+ or 14px+ bold). Use a contrast checker tool to test your color combinations, then update CSS values. The most common failure is light gray text on white backgrounds. Bump #999 on #fff to #595959 or darker to pass.
What is heading order in WCAG and how do I fix it?
WCAG 1.3.1 requires heading levels to follow a logical sequence without skipping levels. For example, an h1 should be followed by h2, not h3. Headings act as a table of contents for screen reader users who navigate by heading. Fix by adjusting heading tags to follow the correct hierarchy, using CSS to control visual size independently of heading level.
Why do form fields need labels for accessibility?
Without a label, screen reader users hear 'edit text' or 'checkbox' with no context about what information to enter. Voice control users cannot target the field by name. WCAG 1.3.1 and 4.1.2 require every form input to have a programmatically associated label. Use a label element with a matching for attribute, or use aria-label for visually hidden labels.