Web Accessibility (A11Y): Building Inclusive Websites

Introduction

Accessibility makes websites usable for all, including people with disabilities. Learn key WCAG techniques and how to avoid common accessibility pitfalls.

Written At

2025-05-25

Updated At

2025-05-25

Reading time

8 minutes

Step 1: Semantic HTML & ARIA Roles

Why it matters: Screen readers rely on proper markup to interpret content.

What to do:

  1. Use native HTML elements (<button>, <nav>) over generic <div> 's.
  2. Add ARIA attributes when semantics aren't enough:
    html
    <div role="alert" aria-live="assertive">
       Error message!
    </div>

Example:

A navigation menu with proper roles:

html
<nav aria-label="Main navigation">
   <ul class="nav_list">
      <li class="nav_list_item">
         <a href="#home" aria-current="page">
            Home 
         </a>
      </li>
   </ul>
 </nav>

Step 2: Keyboard Navigation & Focus Management

Why it matters: Many users rely on keyboards, not mice.

What to do:

  1. Ensure all interactive elements are focusable (use tabindex="0" for custom elements).
  2. Manage focus for modals and dialogs:
    javascript
    function Modal({ isOpen }) {
       const modalRef = useRef(null);
    
       useEffect(() => {
          if (isOpen) {
             modalRef.current.focus();
             trapFocus(modalRef.current);
          }
       }, [isOpen]);
    
       return (
          <div role="dialog" aria-modal="true" tabIndex="-1" ref={modalRef}>
             {/* Modal content */}
          </div>
      );
    }

Example:

A skip-to-content link implementation:

html
<a href="#main" class="skip-link" tabindex="0">
   Skip to main content
</a>

<!-- CSS to show on focus -->
<style>
   .skip-link {
      position: absolute;
      left: -999px;
   }
   .skip-link:focus {
      left: 10px;
   }
</style>

Step 3: Color Contrast & Text Readability

Why it matters: Low contrast excludes users with visual impairments.

What to do:

  1. Verify contrast ratios (minimum 4.5:1 for normal text, 3:1 for large text):
    css
    /* Good contrast example */
    .button {
       background-color: #0056b3; /* Dark blue */
       color: #ffffff; /* White */
       /* Contrast ratio: 7.43:1 */
    }
    
    /* Bad contrast example */
    .bad-button {
       background-color: #a0a0a0; /* Gray */
       color: #f0f0f0; /* Light gray */
       /* Contrast ratio: 1.53:1 */
    }
  2. Provide multiple ways to consume content:
    html
    <img src="chart.png" alt="Sales growth Q1 2023: 15% increase"
       aria-describedby="chart-desc">
    
    <p id="chart-desc" class="visually-hidden">
       Bar chart showing 15% growth in Q1 compared to 10% in Q4 2022.
    <p>
    
    <a href="data.csv">Download raw data<p>

Example:

Accessible form with proper labeling:

html
<form>
   <div class="form-group">
      <label for="email">
         Email address
         <span aria-hidden="true">*</span>
         <span class="visually-hidden">required</span>
      </label>
      <input type="email" id="email" aria-required="true"
         aria-describedby="email-help">
      <small id="email-help">
         We'll never share your email.
      </small>
   </div>
</form>

Conclusion:

Accessibility benefits everyone - from permanent disabilities to temporary impairments like a broken arm. Start small with semantic HTML, then progressively enhance with ARIA and JavaScript. Automated tools catch ~30% of issues - always test with real users including screen reader users.

Related Blogs