← Back to Blog
console.log()

Web Accessibility Guide - Building Inclusive Websites

Make your websites accessible to everyone. Learn WCAG guidelines, ARIA attributes, and accessibility best practices.

accessibilityfrontendweb

Web Accessibility Guide

Over 1 billion people have disabilities. Make your websites work for everyone.

Why Accessibility Matters

  • Legal requirement in many countries
  • Better SEO - accessibility improves search rankings
  • Larger audience - reach more users
  • Better UX - everyone benefits

Semantic HTML

Use the right elements:

<!-- Bad -->
<div class="button" onclick="submit()">Submit</div>

<!-- Good -->
<button type="submit">Submit</button>

<!-- Bad -->
<div class="header">
 <div class="nav">...</div>
</div>

<!-- Good -->
<header>
 <nav>...</nav>
</header>

Keyboard Navigation

Everything should work without a mouse:

/* Never hide focus indicators completely */
button:focus {
 outline: 2px solid #0066cc;
 outline-offset: 2px;
}

/* Skip link for keyboard users */
.skip-link {
 position: absolute;
 top: -40px;
}

.skip-link:focus {
 top: 0;
}
<a href="#main-content" class="skip-link">Skip to main content</a>

Images and Alt Text

<!-- Informative images -->
<img src="chart.png" alt="Sales increased 50% from Q1 to Q2">

<!-- Decorative images -->
<img src="decoration.png" alt="" role="presentation">

<!-- Complex images -->
<figure>
 <img src="infographic.png" alt="Company growth infographic">
 <figcaption>
 Detailed description of the infographic...
 </figcaption>
</figure>

ARIA Attributes

When HTML isn't enough:

<!-- Live regions for dynamic content -->
<div aria-live="polite" aria-atomic="true">
 3 items in cart
</div>

<!-- Custom components -->
<div role="tablist">
 <button role="tab" aria-selected="true" aria-controls="panel1">Tab 1</button>
 <button role="tab" aria-selected="false" aria-controls="panel2">Tab 2</button>
</div>
<div role="tabpanel" id="panel1">Content 1</div>
<div role="tabpanel" id="panel2" hidden>Content 2</div>

<!-- Form validation -->
<input
 type="email"
 aria-invalid="true"
 aria-describedby="email-error"
>
<span id="email-error">Please enter a valid email</span>

Color and Contrast

/* Minimum contrast ratio: 4.5:1 for normal text */
.text {
 color: #333; /* On white background */
 background: #fff;
}

/* Don't rely on color alone */
.error {
 color: #d32f2f;
 border-left: 4px solid #d32f2f;
}
.error::before {
 content: "⚠ ";
}

Forms

<form>
 <label for="email">Email address</label>
 <input
 type="email"
 id="email"
 name="email"
 required
 aria-required="true"
 >

 <fieldset>
 <legend>Notification preferences</legend>
 <label>
 <input type="checkbox" name="email-notifications">
 Email notifications
 </label>
 </fieldset>
</form>

Testing Tools

  • axe DevTools - Browser extension
  • WAVE - Web accessibility evaluator
  • Lighthouse - Built into Chrome
  • Screen readers - NVDA, VoiceOver

Conclusion

Accessibility isn't optional. Start with semantic HTML, test with real users, and continuously improve.