How to Write Accessible Code (That’s Also More Readable & Maintainable)

Melwyn Joseph

25 July 2025 | 12 minute read
Illustration of a developer working at a desk to write accessible code using HTML and clean markup.

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.

ElementPoor PracticeHow It Affects UsersBest Practice
StructureUsing <div> or <span> for layout or headingsScreen readers can’t understand page layout or skip between sections. Users get lost in the content.Use semantic tags like <main>, <nav>, <section>, <h1>
FormsLeaving 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 ManagementRemoving or hiding focus outlinesKeyboard users can’t see where they are. They get stuck or lost while navigating.Ensure focus styles are visible on all interactive elements
Keyboard SupportRelying only on mouse-based interactionsUsers who can’t use a mouse can’t interact with your UI.Ensure all actions work with Tab, Enter, and Space
Tab OrderCreating illogical or broken tab flowsKeyboard and screen reader users experience confusing navigation or miss important content.Follow logical DOM order; use tabindex only when needed
Skip Links & LandmarksSkipping over repeated navigation blocksUsers must tab through every menu repeatedly. It’s slow and frustrating.Add a skip link and use structural landmarks like <main>
Error HandlingShowing visual-only error messages out of contextScreen 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 ContentUpdating content silently without announcementsScreen reader users won’t know that anything changed.Use ARIA live regions (aria-live="polite") for updates
Interaction PatternsUsing <div> or <span> as interactive components without accessibility supportUsers 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 DesignUsing fixed widths or pixel-based sizingZoomed text or small screens break the layout or hide content.Use relative units (em, rem, %) and media queries
ARIA UsageOverusing or misapplying ARIA roles and attributesConfuses screen readers, causing broken or misleading experiences.Use ARIA only when needed, and follow correct patterns
Page MetadataSkipping page <title> or missing lang attributeScreen 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

  1. Use semantic HTML instead of generic elements
  2. Label every form field clearly
  3. Keep focus styles visible for all users
  4. Make all functionality work with a keyboard
  5. Maintain a logical tab order
  6. Add skip links and use landmarks for easy navigation
  7. Make error messages accessible
  8. Use ARIA live regions to announce live content updates
  9. Use native elements for interactions
  10. Use relative units for responsive layouts
  11. Use ARIA roles only when necessary
  12. 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.


Article by

Latest Article

An illustration depicting various elements of an SEO audit, including a large magnifying glass over the word "SEO" on a webpage interface.
07 November 2025

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 […]

Read More
WebYes at Web Summit 2025 – event banner showing WebYes logo above the Web Summit 2025 logo with event dates November 10–13 in Lisbon, Portugal.
04 November 2025

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 […]

Read More
Illustration of a browser window with an accessibility icon and a puzzle piece symbol representing a Chrome extension.
29 October 2025

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 […]

Read More
Illustration showing monthly, quarterly, and annual options, emphasising how often you should audit your website.
24 October 2025

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?

Read More