Munsif.
AboutExperienceProjectsAchievementsBlogsContact
HomeAboutExperienceProjectsAchievementsBlogsContact
Munsif.

Frontend Developer crafting scalable web applications with modern technologies and clean code practices.

Quick Links

  • About
  • Experience
  • Projects
  • Achievements

Connect

© 2026 Shaik Munsif. All rights reserved.

Built with Next.js & Tailwind

0%
Welcome back!Continue where you left off
Back to Blogs
Accessibility

Web Accessibility 101: A Developer's Guide to WCAG & ARIA

Accessibility isn't optional—it's essential. Master the POUR principles, understand ARIA attributes like aria-label & aria-live, and learn how to build inclusive web experiences.

Feb 3, 202620 min read
AccessibilityWCAGARIAFrontendBest Practices

Introduction

The web was designed to work for everyone, regardless of their hardware, software, language, location, or ability. When the web meets this goal, it is accessible to people with a diverse range of hearing, movement, sight, and cognitive ability.

However, 96.3% of the top 1 million homepages had detectable accessibility failures in 2023 (WebAIM).

Building accessible websites isn't just about avoiding lawsuits or following rules; it's about empathy and user experience. A website that is easy for a screen reader to navigate is usually cleaner, faster, and better for SEO for everyone else.

In this guide, we'll demystify the WCAG (Web Content Accessibility Guidelines) and look at practical ways to fix common issues using HTML and ARIA.


The 4 Principles of Accessibility (POUR)

The WCAG guidelines are organized around four core principles. If your site fails one of these, it fails accessibility.

1. Perceivable

Information and user interface components must be presentable to users in ways they can perceive.

  • Example: Text alternatives (Alt text) for images so blind users can "see" them via screen readers.
  • Example: Captions for videos for deaf users.

2. Operable

User interface components and navigation must be operable.

  • Example: Everything must be clickable via keyboard only (no mouse).
  • Example: Users must have enough time to read and use content (no 3-second auto-closing modals).

3. Understandable

Information and the operation of user interface must be understandable.

  • Example: Predictable navigation (menus shouldn't change order randomly).
  • Example: Error messages should clearly explain what went wrong, not just turn red.

4. Robust

Content must be robust enough that it can be interpreted reliably by a wide variety of user agents, including assistive technologies.

  • Example: Writing valid HTML so browsers and screen readers don't break when parsing your code.

Semantic HTML: The Foundation

The single biggest thing you can do for accessibility is usually the simplest: Use correct HTML tags.

The Button vs. Div Debate

This is the most common accessibility violation on the web.

Bad:

// This is invisible to keyboard users and screen readers
<div onClick={submitForm} className="btn">
  Submit
</div>

Good:

// This gets focus, keyboard support, and announces "Button" automatically
<button onClick={submitForm} className="btn">
  Submit
</button>

If you must use a div (don't), you have to manually add role="button", tabIndex="0", and keydown listeners for Enter/Space. Why do all that work when <button> does it for free?


ARIA Deep Dive: Use It Wisely

ARIA (Accessible Rich Internet Applications) is a set of attributes that allow you to modify how an element translates to the Accessibility Tree.

The First Rule of ARIA: Use native HTML elements to satisfy the requirement effectively. If you can use a native HTML element or attribute, do so.

However, typically when building complex components like Modals, Accordions, or Custom Dropdowns, we need ARIA.

1. aria-label vs aria-labelledby

These provide an accessible name for an element.

Scenario: An icon-only button (e.g., a "Trash" icon for delete).

<!-- BAD: Screen reader says "Button" (What button??) -->
<button>
  <i class="fa fa-trash"></i>
</button>

<!-- GOOD: Screen reader says "Button, Delete Item" -->
<button aria-label="Delete Item">
  <i class="fa fa-trash"></i>
</button>

Scenario: A modal dialog whose title is already visible on screen.

<div role="dialog" aria-labelledby="modal-title">
  <h2 id="modal-title">Confirm Deletion</h2>
  <p>Are you sure?</p>
</div>

Using aria-labelledby avoids duplication by pointing to an existing ID.

2. aria-expanded & aria-controls

These are essential for Accordions and Dropdowns. They tell the user "This button controls meaningful content, and it is currently open/closed."

<!-- Button controlling the accordion panel -->
<button
  aria-expanded="false" 
  aria-controls="accordion-content-1"
  onClick={toggleAccordion}
>
  Show Details
</button>

<!-- The content panel itself -->
<div id="accordion-content-1" hidden>
  <p>Here are the details...</p>
</div>

When the user clicks, you must toggle aria-expanded to "true". Without this, a blind user has no idea that clicking the button revealed new content.

3. aria-live for Dynamic Content

How do you tell a screen reader user that a "Toast" message just popped up in the corner? If you don't tell them, they won't know.

  • aria-live="polite": Waits for the user to stop typing/interaction, then announces the update. (Good for Form Errors, Toasts).
  • aria-live="assertive": Interrupts the user immediately. (Good for Critical server errors, "Session Timeout").
<div role="status" aria-live="polite">
  {message && <span>{message}</span>}
</div>

4. aria-hidden="true"

Use this to hide decorative content from screen readers.

<!-- The user hears "Button, Settings". They don't need to hear "Gear Icon" -->
<button>
  <span class="icon-gear" aria-hidden="true"></span>
  Settings
</button>

5. aria-describedby

While aria-label gives an element a name, aria-describedby gives it a description. This is perfect for tooltips or helper text.

<label for="password">Password</label>
<input 
  id="password" 
  type="password" 
  aria-describedby="password-help"
/>
<span id="password-help">Must be 8 characters long</span>

When the user focuses the input, the screen reader announces: "Password, secure edit text... Must be 8 characters long."

6. aria-current

Use this to indicate the current item within a navigation set (like pagination or a sidebar).

Note: Don't use aria-selected for links! aria-selected is for Tabs and Grids.

<nav>
  <a href="/home">Home</a>
  <!-- Tells the user "This is the page you are on" -->
  <a href="/about" aria-current="page">About</a>
  <a href="/contact">Contact</a>
</nav>

7. Form Accessibility: aria-invalid

Don't just turn the border red when a form has an error. Blind users won't see the red border.

<input 
  type="email" 
  aria-invalid="true" 
  aria-errormessage="email-error"
/>
<span id="email-error" class="error-text">Please enter a valid email.</span>

This ensures the error state is programmatic, not just visual.


Essential Checklist

Before you ship, check these 5 things:

  1. Keyboard Navigation: Can you Tab through the entire page and use every interactive element without a mouse?
  2. Focus Styles: Is there a visible "outline" or focus ring when you Tab to a link/button? (Never do outline: none!)
  3. Contrast: Is the text easy to read? (Use tools like the Chrome Inspector to check ratios).
  4. Alt Text: Do all images have alt attributes? (Empty alt="" is fine for decorative images).
  5. Headings: Do you use h1 through h6 in logical order? (Don't skip from h1 to h4 just for sizing).

Common Interview Questions

I searched the top tech interview resources, and these are the most common accessibility questions asked to Frontend Engineers.

Q1: What is a "Skip Link" and why is it important?

A "Skip Link" is a hidden link at the very top of the page (usually "Skip to Content").

  • Purpose: It allows keyboard users to bypass repetitive navigation menus and jump straight to the main content.
  • Behavior: It should be hidden by default but become visible when it receives focus (via the Tab key). Without it, keyboard users have to hit Tab 20+ times on every page load just to read the article.

Q2: How do you handle Focus Management in a Single Page Application (SPA)?

In SPAs (like React/Next.js), when a user navigates to a new page, the focus often remains on the last clicked link (or is lost entirely).

  • The Fix: You must manually move focus to the top of the new page (usually the <h1> or a wrapper div) after a route change.
  • Modals: When opening a modal, focus should get trapped inside it. When closing it, focus should return to the button that opened it.

Q3: What are the specific WCAG Contrast Ratio requirements?

  • AA Standard (Minimum):
    • 4.5:1 for normal text.
    • 3.0:1 for large text (18pt+ or 14pt bold).
  • AAA Standard (Enhanced):
    • 7.0:1 for normal text.
    • 4.5:1 for large text.
  • UI Components: Buttons and inputs must have a 3.0:1 contrast ratio against the background.

Q4: What is the difference between aria-label, aria-labelledby, and aria-describedby?

  • aria-label: Use for invisible labels (e.g., a "close" icon button).
  • aria-labelledby: Use to point to another element that acts as the label (e.g., a modal header acting as the modal's label).
  • aria-describedby: Use for additional info, like helper text ("Password must be 8 chars").

Q5: "No ARIA is better than Bad ARIA." Explain.

Native HTML elements (buttons, inputs, links) have accessibility baked in (focus states, keyboard listeners, screen reader roles).

  • Bad ARIA: <div role="button">Click</div> (Fails content checks, no keyboard support).
  • Good ARIA: Use it ONLY when filling gaps in HTML (like custom dropdowns or popups).
  • Rule: If HTML can do it, don't use ARIA.

Summary

Accessibility is a journey, not a destination. You won't get everything perfect on day one, but understanding Semantic HTML and properly applying ARIA where needed will put you ahead of 96% of the web.

Build for everyone. The web is better that way.

🧠 Test Your Knowledge

Now that you've learned the concepts, let's see if you can apply them! Take this quick quiz to test your understanding.

Written by

Shaik Munsif

Read more articles

Found this helpful? Share it with your network!

Question 1 of 15Easy
Score: 0/0

What does the 'P' in the POUR principles stand for?