Skip to main content
Accessibility Conformance

How to fix the most common issues

Before and after code for the problems scans find most often.

These are the rules scans report most often, with a failing example and a corrected one for each. Search for the rule name on your Issues tab (for example color-contrast) to see how many times it occurs on your site.

color-contrast: text is hard to read

Why it matters. People with low vision, color blindness, or a phone in bright sunlight need enough difference between text and its background. WCAG 1.4.3 asks for a contrast ratio of at least 4.5 to 1 for normal text, and 3 to 1 for large text (18pt, or 14pt bold).

Fails

<p style="color: #94a3b8; background: #ffffff;">
  Secondary details
</p>

Light grey on white is only 2.6 to 1.

Passes

<p style="color: #475569; background: #ffffff;">
  Secondary details
</p>

Darker slate on white is 7.6 to 1.

How to fix it. Darken the text or lighten the background until it passes. Fix the color once in your theme or CSS variables rather than element by element. Check any pair with the contrast checker. Remember placeholder text, text over images, and text in hover and disabled states.

image-alt: images with no text alternative

Why it matters. A screen reader cannot describe a picture without alt text (WCAG 1.1.1).

Fails

<img src="/team.jpg">

Passes

<img src="/team.jpg"
     alt="Five staff members standing outside the front office">

How to fix it. Describe what the image shows or what it does, as briefly as you can. If an image is purely decorative, use an empty alt so screen readers skip it: alt="". If the image is inside a link, the alt text should say where the link goes. A scan can tell that alt text is missing but cannot judge whether your text is good, so review it yourself.

label: form fields with no label

Why it matters. Without a label, a screen reader user hears "edit text" with no clue what to type, and sighted users lose the clickable label target (WCAG 1.3.1, 3.3.2, 4.1.2).

Fails

<input type="email" placeholder="Email">

A placeholder disappears as soon as someone types and is not a reliable label.

Passes

<label for="email">Email address</label>
<input type="email" id="email" autocomplete="email">

How to fix it. Give every field a visible <label> tied to the field by for and id. If the design truly has no room for visible text, use aria-label as a last resort.

Why it matters. A link that holds only an icon is announced as just "link" (WCAG 2.4.4, 4.1.2). People who jump through a list of links hear a row of meaningless entries.

Fails

<a href="https://example.com/cart">
  <svg viewBox="0 0 24 24">...</svg>
</a>

Passes

<a href="https://example.com/cart"
   aria-label="View cart">
  <svg viewBox="0 0 24 24" aria-hidden="true">...</svg>
</a>

How to fix it. Add visible text, or an aria-label that says where the link goes. Avoid "click here" and "read more" on their own. Use text that makes sense out of context, such as "Read the pricing guide".

button-name: buttons with no name

Fails

<button class="close">
  <svg viewBox="0 0 24 24">...</svg>
</button>

Passes

<button class="close" aria-label="Close dialog">
  <svg viewBox="0 0 24 24" aria-hidden="true">...</svg>
</button>

How to fix it. The same idea as links (WCAG 4.1.2). Icon-only buttons such as close, menu, search and carousel arrows are the usual culprits.

html-has-lang and document-title: page basics

Why it matters. Screen readers use the page language to choose the right pronunciation (WCAG 3.1.1), and the page title is the first thing announced when a page loads (WCAG 2.4.2).

Fails

<html>
  <head></head>

Passes

<html lang="en">
  <head>
    <title>Pricing | Example Company</title>
  </head>

How to fix it. Set lang on the <html> tag and give every page a unique, descriptive <title>.

Why it matters. If a link inside a paragraph is only a different color, people who cannot tell the colors apart cannot see that it is a link (WCAG 1.4.1).

Fails

a { color: #0369a1; text-decoration: none; }

Passes

a { color: #0369a1; text-decoration: underline; }

How to fix it. Keep the underline for links in running text. Remove it only in navigation where position makes the purpose clear.

aria-required-children: ARIA roles with the wrong contents

Why it matters. Some ARIA roles only work when they contain certain child roles. A menu with no menuitem inside it is announced as an empty menu.

Fails

<div role="menu">
  <div>Profile</div>
  <div>Sign out</div>
</div>

Passes

<div role="menu">
  <button role="menuitem">Profile</button>
  <button role="menuitem">Sign out</button>
</div>

How to fix it. Add the missing child roles. If you do not need custom widget behavior, remove the ARIA and use plain HTML such as a list of links, which needs no extra work. Use the ARIA inspector to check a snippet.

heading-order: skipped heading levels

Why it matters. Screen reader users navigate by headings. A jump from a level 2 to a level 4 suggests missing content. This is a best-practice suggestion rather than a WCAG failure.

Fails

<h2>Our services</h2>
<h4>Audits</h4>

Passes

<h2>Our services</h2>
<h3>Audits</h3>

How to fix it. Choose heading levels for structure, not size. Use CSS to change how big a heading looks.

region and landmark rules: page structure

Why it matters. Landmarks let people skip straight to the main content or the navigation. The rules region, landmark-one-main and landmark-unique are best-practice suggestions. Each page should have one <main>, and all visible content should sit inside a landmark.

Fails

<body>
  <div class="header">...</div>
  <div class="content">...</div>
  <div class="footer">...</div>
</body>

Passes

<body>
  <header>...</header>
  <nav aria-label="Main">...</nav>
  <main>...</main>
  <footer>...</footer>
</body>

If a page has two navs, give each its own aria-label.

These often come from a theme or page builder. Fixing the template once usually clears the rule across many pages.

Still stuck? Contact us with your site address and what you expected to happen.