How to Write Accessible Code (That’s Also More Readable & Maintainable)
Code that’s not accessible is not only poor-quality, but it can also exclude as many as 1 in 4 people from accessing your website and its content. As a developer, learning to write accessible code is one of the most impactful things you can do to build inclusive, user-friendly experiences.
In this guide, we’ll look at 12 code-level elements that directly impact accessibility. You’ll see what to avoid, what to do instead, and how each one helps real users. The goal is to make your code easier to use, read, and maintain – for everyone.
Why You Should Write Accessible Code
Writing accessible code comes with real benefits, like:
- It’s inclusive by design
- It’s easier to read
- It’s easier to maintain
Let’s look at each of these in detail.
1. It’s inclusive by design
Accessible code works for everyone, including people using screen readers, keyboard navigation, zoomed layouts, or other assistive tools. It removes barriers and ensures no one is left out just because of how they access the web. Inclusion starts in the code.
2. It’s easier to read
Semantic HTML and clear structure make your code easier for anyone to understand – teammates, contributors, even your future self. Instead of digging through anonymous <div>s or guessing what something does, people can scan your markup and quickly see its purpose.
3. It’s easier to maintain
Accessible code relies on native behaviour, semantic patterns, and predictable structure. That means fewer hacks and fewer bugs. It also makes updates, refactors, and team handoffs smoother, especially as projects grow and developers change.
“Accessible code isn’t just more usable for everyone, it’s also often cleaner code! Using semantic HTML, for instance, often makes it a lot easier to read and understand a page’s HTML.” – Viktor Köves (Front-End Engineer & Accessibility Specialist)
12 Code Elements That Impact Accessibility
Accessibility starts in your code. Here are 12 areas you can focus on to make your markup more inclusive and user-friendly.
| Element | Poor Practice | How It Affects Users | Best Practice |
|---|---|---|---|
| Structure | Using <div> or <span> for layout or headings | Screen readers can’t understand page layout or skip between sections. Users get lost in the content. | Use semantic tags like <main>, <nav>, <section>, <h1> |
| Forms | Leaving inputs without a proper <label> | Screen reader users won’t know what a field is for. Sighted users may also struggle with clarity. | Add <label> and link it using the for attribute |
| Focus Management | Removing or hiding focus outlines | Keyboard users can’t see where they are. They get stuck or lost while navigating. | Ensure focus styles are visible on all interactive elements |
| Keyboard Support | Relying only on mouse-based interactions | Users who can’t use a mouse can’t interact with your UI. | Ensure all actions work with Tab, Enter, and Space |
| Tab Order | Creating illogical or broken tab flows | Keyboard and screen reader users experience confusing navigation or miss important content. | Follow logical DOM order; use tabindex only when needed |
| Skip Links & Landmarks | Skipping over repeated navigation blocks | Users must tab through every menu repeatedly. It’s slow and frustrating. | Add a skip link and use structural landmarks like <main> |
| Error Handling | Showing visual-only error messages out of context | Screen reader users may never know there was an error or where to fix it. | Connect errors to fields using aria-describedby or inline text |
| Live Content | Updating content silently without announcements | Screen reader users won’t know that anything changed. | Use ARIA live regions (aria-live="polite") for updates |
| Interaction Patterns | Using <div> or <span> as interactive components without accessibility support | Users can’t activate controls with a keyboard or screen reader. The UI becomes unusable. | Use native elements (<button>) or add role, keyboard handlers, and focus support |
| Responsive Design | Using fixed widths or pixel-based sizing | Zoomed text or small screens break the layout or hide content. | Use relative units (em, rem, %) and media queries |
| ARIA Usage | Overusing or misapplying ARIA roles and attributes | Confuses screen readers, causing broken or misleading experiences. | Use ARIA only when needed, and follow correct patterns |
| Page Metadata | Skipping page <title> or missing lang attribute | Screen readers may mispronounce text or miss the page context. | Set descriptive titles and define the lang attribute |
Not sure if your website’s code is accessible? Run a free scan to check for accessibility issues in your site’s markup.
How to Write Accessible Code
- Use semantic HTML instead of generic elements
- Label every form field clearly
- Keep focus styles visible for all users
- Make all functionality work with a keyboard
- Maintain a logical tab order
- Add skip links and use landmarks for easy navigation
- Make error messages accessible
- Use ARIA live regions to announce live content updates
- Use native elements for interactions
- Use relative units for responsive layouts
- Use ARIA roles only when necessary
- Set a descriptive page title and language attribute
Let’s walk through each of these 12 elements in detail, with examples, best practices, and how they improve the user experience.
1. Use semantic HTML instead of generic elements
Using semantic HTML is one of the easiest ways to make your code more accessible. It also makes it easier to scan, debug, and collaborate on. Instead of using <div> and <span> for everything, use HTML elements that convey meaning, like <main>, <nav>, and heading tags in the right order.
Example:
<!-- ❌ Poor Practice -->
<div class="header">Welcome</div>
<div class="content"><div class="section-title">About</div></div>
<!-- ✅ Best Practice -->
<header><h1>Welcome</h1></header>
<main><section><h2>About</h2></section></main>
By doing so, screen reader users can navigate your content more easily using headings and landmarks. It solves the problem of users getting stuck in long pages without any clear structure, making it easier for them to jump to what matters.
2. Label every form field clearly
Labelling form fields properly helps users understand what each input is for. It also improves screen reader compatibility and form usability. Instead of relying on placeholders or visual cues, use <label> elements that are explicitly linked to inputs.
Example:
<!-- ❌ Poor Practice -->
<input type="email" placeholder="Email">
<!-- ✅ Best Practice -->
<label for="email">Email</label>
<input id="email" type="email">
Doing so helps screen reader users identify each field correctly. It solves the problem of users guessing input purposes or missing context when placeholders vanish during typing.
3. Keep focus styles visible for all users
Visible focus styles help keyboard users understand where they are on the page. It also helps with debugging and testing the interaction flow. Instead of removing focus outlines, apply a clear and consistent style that fits your design.
Example:
/* ❌ Poor Practice */
*:focus {
outline: none;
}
/* ✅ Best Practice */
*:focus {
outline: 2px solid #005fcc;
}
By keeping focus visible, you make sure keyboard users always know what they’re interacting with. It solves the frustration of losing track of focus, especially in forms, menus, and dialogs.
4. Make all functionality work with a keyboard
Making functionality keyboard-friendly ensures that users can interact without needing a mouse. It also helps test and verify interaction logic. Instead of using mouse-only events like onclick on non-interactive elements, use buttons and support Enter and Space.
Example:
<!-- ❌ Poor Practice -->
<div onclick="submitForm()">Submit</div>
<!-- ✅ Best Practice -->
<button onclick="submitForm()">Submit</button>
By doing so, you allow users who rely on a keyboard to use every feature on your site. It solves the issue of functionality being completely blocked for users who can’t use a mouse.
5. Maintain a logical tab order
A logical tab order helps users navigate your interface quickly and without confusion. It also makes testing smoother and reduces edge-case bugs. Instead of forcing tab order with tabindex values, rely on natural DOM order and only use overrides when necessary.
Example:
<!-- ❌ Poor Practice -->
<div tabindex="3">Step 3</div>
<div tabindex="1">Step 1</div>
<div tabindex="2">Step 2</div>
<!-- ✅ Best Practice -->
<div>Step 1</div>
<div>Step 2</div>
<div>Step 3</div>
That way, users move through your interface in a predictable, logical sequence. It prevents disorientation caused by jumping around unexpectedly or skipping key elements.
6. Add skip links and use landmarks for easy navigation
Skip links and landmarks let users jump to the main content faster. It also gives screen readers a clear structure to follow. Instead of making users tab through every menu item, provide a “skip to content” link and use semantic landmarks like <main> and <nav>.
Example:
<!-- ✅ Best Practice -->
<a href="#main" class="skip-link">Skip to content</a>
<nav>...</nav>
<main id="main">...</main>
By doing so, keyboard and screen reader users can avoid repetitive navigation and reach the main content immediately. It solves the problem of having to tab through long menus on every single page.
7. Make error messages accessible
Announcing form errors helps users fix mistakes faster and reduces frustration. It also makes your form more reliable for screen reader users. Instead of showing error messages visually only, connect them to inputs using aria-describedby or inline descriptions.
Example:
<!-- ❌ Poor Practice -->
<p class="error">Email is required.</p>
<input type="email">
<!-- ✅ Best Practice -->
<label for="email">Email</label>
<input id="email" type="email" aria-describedby="email-error">
<p id="email-error" class="error">Email is required.</p>
By doing so, all users, including those using screen readers, get immediate feedback tied directly to the form field. It solves the issue of users not knowing where the error is or how to fix it.
8. Use ARIA live regions to announce live content updates
ARIA live regions let screen readers pick up on changes without a page reload. This helps users know when something has been updated, like a form message or cart count. Instead of silently updating content, wrap those updates in a region with aria-live.
Example:
<!-- ✅ Best Practice -->
<div aria-live="polite" id="status"></div>
<script>
document.getElementById('status').textContent = 'Item added to cart.';
</script>
This approach allows screen reader users to hear content updates in real-time. It prevents important messages, like form success or errors, from going completely unnoticed.
9. Use native elements for interactions
Interactive components should work with keyboard and assistive tech, not just a mouse. This also improves test coverage and avoids surprises. Instead of using <div>s for clickable elements, use buttons or add proper roles, keyboard handlers, and focus support.
Example:
<!-- ❌ Poor Practice -->
<div onclick="toggleMenu()">Menu</div>
<!-- ✅ Best Practice -->
<div role="button" tabindex="0" onclick="toggleMenu()" onkeydown="if(event.key==='Enter') toggleMenu()">Menu</div>
By doing so, users who navigate with keyboards or screen readers can interact with your custom components just like native ones. It removes barriers that would otherwise make your UI unusable to them.
10. Use relative units for responsive layouts
Using relative units helps your content scale across devices and zoom levels. It also prevents broken layouts and overlapping content. Instead of hardcoding pixels, use rem, em, or % along with media queries to create flexible, accessible designs.
Example:
/* ❌ Poor Practice */
.container {
width: 800px;
font-size: 14px;
}
/* ✅ Best Practice */
.container {
width: 80%;
font-size: 1rem;
}
@media (min-width: 600px) {
.container {
max-width: 40rem;
}
}
By doing so, you write accessible code that adapts when users zoom or increase font size. It solves issues like overlapping text, horizontal scroll, and unreadable UI on smaller or magnified screens.
11. Use ARIA roles only when necessary
ARIA is powerful, but often misused. It’s best used when native HTML can’t express the same meaning. Instead of reaching for ARIA first, use semantic elements like <button>, <form>, or <dialog> wherever possible.
Example:
<!-- ❌ Poor Practice -->
<div role="button">Click me</div>
<!-- ✅ Best Practice -->
<button>Click me</button>
By relying on native HTML elements, you ensure the correct roles, behaviours, and keyboard support are built in. It solves problems caused by misapplied roles that confuse assistive technologies.
12. Set a descriptive page title and language attribute
Setting the page title and language helps screen readers understand what the page is and how to pronounce its content. It also improves navigation and SEO. Instead of leaving these out, set a clear <title> and add a lang attribute to your <html> tag.
Example:
<!-- ✅ Best Practice -->
<html lang="en">
<head>
<title>Dashboard – MyApp</title>
</head>
</html>
By doing so, users immediately know where they are and hear the page content in the correct language. It solves confusion caused by missing context or incorrect screen reader pronunciation.
Start Writing Accessible Code Today
It’s normal to feel a bit unsure when you’re adding something new to your workflow, especially accessibility. But once you get started, you’ll see how much of it aligns with clean, future-proof code that works better for everyone.
Start with just one improvement – a better label, a visible focus style, or a semantic tag in the right place. Every fix helps someone use your site more easily. And in the process, you’ll write cleaner, more reliable code that’s easier for everyone to work with – including you.
Write accessible code, and you’ll write code that lasts, scales, and includes.
Latest Article
SEO Audit – How to Conduct a Complete Site Check
Your website may look great, but that alone does not guarantee visibility in search results. Without proper optimisation, even a well-designed site can struggle to attract visitors. An SEO audit helps you uncover what’s stopping your site from ranking higher on Google. It analyses every important element that affects visibility, traffic, and performance. In this […]
Join WebYes at Web Summit 2025 in Lisbon
WebYes is heading to Web Summit 2025, happening November 10–13 at the MEO Arena and Feira Internacional de Lisboa (FIL) in Lisbon, Portugal. Key Event Details What We’re Showcasing We’re thrilled to share that WebYes has been selected for the Startup Showcase at Web Summit 2025. During this quickfire presentation, we’ll showcase our website audit […]
Best Accessibility Checker Chrome Extensions for Testing
Chrome extensions make accessibility testing quick and easy. They help you spot basic issues right in your browser, making it easier to start improving your site’s accessibility. In this guide, we’ve listed some of the best accessibility checker Chrome extensions. They can help you find common issues and move your website toward better accessibility. How […]
How Often Should You Audit Your Website?
Just as we undergo regular health checkups to ensure our body is functioning properly and free from diseases, your website also needs periodic checkups to maintain optimal performance and stay issue-free. But how often should you audit your website?