Imagine you're building a sleek, modern website, it looks great, loads fast, and works beautifully on all devices. But one day, a user emails you: "I can't navigate your site with my screen reader. I couldn’t even subscribe to the newsletter." That’s when you realize something critical was missing accessibility. Accessibility isn't just a checklist; it's a way of ensuring everyone, regardless of ability, can use your website. From screen reader users to keyboard navigators, making your site inclusive means better UX for all. In this guide, we’ll demystify how to:
Let’s start building for everyone.
Semantic HTML means using HTML tags that describe the content's meaning, not just its appearance. These tags tell browsers and assistive technologies what kind of content they’re interacting with, making your website more meaningful, especially for people using screen readers.
Good for screen readers, SEO, and other tools to understand your layout.
Tag | Use For | Example |
<header> | Page or section header | Top section of page |
<nav> | Navigation links | Menus or link bars |
<main> | Main content (1 per page) | Article, dashboard, etc. |
<section> | Thematic grouping | Features, Services |
<article> | Self-contained content | Blog post, comment |
<aside> | Secondary content | Sidebars, ads, notes |
<footer> | Page or section footer | Copyright, contact |
<h1> to <h6> | Headings (semantic levels) | Titles and subtitles |
<ul>, <ol>, <li> | Lists | FAQs, features |
<form> | Group of input fields | Sign-up or search |
<label> | Label for form field | Name, Email |
<button> | Clickable actions | Submit, Next |
<a> | Navigation links | Internal or external |
Start with HTML that means something. Don’t use a <div> or <span> just because it works visually use a <button> if it’s clickable, a <nav> if it’s navigation, and so on.
<header>
<nav>
<a href="/">Home</a>
</nav>
</header>
<main>
<section>
<h2>Features</h2>
<p>Explore powerful tools.</p>
</section>
</main>
<footer>
<p>© 2025</p>
</footer>
ARIA stands for Accessible Rich Internet Applications. It allows you to fill in accessibility gaps when you're building custom UI components that native HTML doesn’t support well (like custom modals, tabs, dropdowns, etc.)
Aria Attribute | Use case |
aria-label | Label for element with no visible text |
aria-hidden=”true” | Hide from screen readers |
aria-live | Announce dynamic content updates |
aria-expanded | Toggled state (dropdowns, accordions) |
aria-controls | Describes what element is controlled |
role=”dialog” | Custom modals |
role=”tablist”, role=”tab” | Custom tab interfaces |
Example
<button aria-expanded="false" aria-controls="dropdown1">Menu</button>
<ul id="dropdown1" hidden>
<li>Item 1</li>
</ul>
ARIA is powerful, but it can cause more harm than good if misused. You should avoid ARIA:
Experience seamless collaboration and exceptional results.
Example of What Not to Do:
<!-- Avoid this -->
<div role="button">Click me</div>
Correct Semantic Version:
<button>Click me</button>
Sometimes the visible label for an element comes from another part of the page. Use ‘aria-labelledby’ to associate it.
Example:
<div role="dialog" aria-labelledby="dialog-title">
<h2 id="dialog-title">Subscribe</h2>
<p>Sign up for weekly updates.</p>
</div>
This is helpful when you want to add supporting context, like form hints or validation messages.
Example:
<label for="email">Email</label>
<input id="email" aria-describedby="email-hint email-error" />
<p id="email-hint">We'll never share your email.</p>
<p id="email-error" style="color:red;">Email is required.</p>
Screen readers will read: “Email. We’ll never share your email. Email is required.”
Sometimes seeing the difference makes it click. Here are the examples of accessible vs. non-accessible code:
<div onclick="submitForm()">Submit</div>
No role or semantics
Not keyboard accessible
<button onclick="submitForm()">Submit</button>
Screen reader-friendly
Built-in keyboard support
<input type="text" placeholder="Your Name">
No label for screen readers
<label for="name">Name</label>
<input type="text" id="name">
Proper label association
Experience seamless collaboration and exceptional results.
React developers need to consider a few extra steps:
Use ‘htmlFor’ instead of ‘for’ in labels:
<label htmlFor="email">Email</label>
<input id="email" type="email" />
Manage keyboard events on custom components:
<div role="button" tabIndex={0} onKeyDown={handleKeyDown} onClick={handleClick}>
Toggle
</div>
Use ‘aria-live’ for dynamically changing content:
<div aria-live="polite">{message}</div>
Consider accessible libraries like @radix-ui/react-*, reach-ui, or react-aria.
Accessibility is more than code; it's about real people. Imagine a user navigating your site using only a keyboard or a screen reader:
"I couldn't find the checkout button on your site. I had to ask a friend to help."
Or someone with color blindness:
"I didn’t realize the red box meant an error. There was no text or icon."
Designing with accessibility in mind makes sure everyone can access what you’ve built.
Goal | Use |
Basic structure and meaning | Semantic HTML |
Label an element (no text) | aria-label or aria-labelledby |
Add extra instructions | aria-describedby |
Dynamic or custom elements | ARIA roles/attributes |
Hide decorative content | aria-hidden="true" |
Accessibility isn't about perfection, it's about progress. The more thoughtful we are about the people who use our sites and apps, the more inclusive the web becomes for everyone. You don’t need to know everything or get it 100% right on the first try. What matters is the intention to include, the willingness to learn, and the small steps taken consistently.By choosing semantic HTML, using ARIA only when needed, and testing with real users or screen readers, you're creating something that welcomes everyone, not just the majority.Accessibility isn't just a developer's responsibility, it's a mindset. And by reading this guide, you're already on the right path.
Keep going. Keep building. And keep including.