An Introduction to Web Accessibility

If you’re looking for a comprehensive introduction to web accessibility, this article is for you. I’ll introduce web accessibility, how it is measured by the WCAG and simple but impactful changes you can make to your sites today to make them more accessible.

Table of Contents


Web accessibility is design that works for everyone, regardless of the hardware and software they use to access your site. This involves understanding your fellow web users to anticipate their needs and how they consume information to build better experiences.

Here are some videos on the variety of software and hardware people use to surf the web. I recommend watching these videos, as they provide additional context and motivation for the rest of the article.

Accessible websites increase useability for everyone.

Measuring Web Accessibility

The Web Content Accessibility Guidelines (WCAG are a systematic means of ensuring your website is accessible. It is also the standard used in many organizations, and is the basis of accessibility legislation.

There are 2 versions of the WCAG that are widely used: 2.0 and 2.1. WCAG 2.1 introduces additional success criteria and is backwards compatible with WCAG 2.0. Thus, using WCAG 2.1 for new content is recommended.

WCAG 2.1 consists of 13 guidelines, founded on the following POUR principles:

  1. Perceivable - information and UI elements are presented to users in ways they can perceive. Examples include alt text in images and captions in videos.
  2. Operable - UI elements must be operable by users, and shouldn’t require interactions that users can’t perform. For example, keyboard compatibility for users who are not using the mouse.
  3. Understandable - information and the operation of the UI must be understandable. For example, using clear language in text content, and descriptive error messages to make it easier to correct forms.
  4. Robust - content should be robust enough to be reliably interpreted by different browsers, assistive technologies and other user agents. This also means compatibility with future devices and interfaces which may not exist today. For example, using valid HTML so that it can be reliably interpreted.

Choosing a Level of Conformance

Each WCAG guideline contains testable success criteria which can be used to audit for conformance. For each success criteria, a website passes by implementing it correctly, and fails otherwise. There are 3 conformance levels, which represent things that you must do, should do or could do:

Level AA is the generally accepted level of compliance that websites should attain.

Websites should comply to as many AAA success criteria as they can, but full AAA conformance is impossible for many sites. For example, replacing advanced terminology or jargon with simpler language for a website on web development to conform to success criteria 3.1.5 would make it unuseable by the intended audience.

Getting Started

The rest of this article introduces some simple things you can do to make your websites more accessible.

This is most effective when done for new functionality during development before it goes out for code review. It is easiest to fix problems at this stage of the development cycle, as they are addressed before it affects users.

You can also check existing content to ensure they implement the following best practices.

The techniques discussed here predate the rise of React and other frontend libraries, and are relevant regardless of what technologies are used.

Use Semantic HTML

Semantic HTML is the use of HTML elements according to what they are, instead of how they render in browsers by default. This enriches web content with meaning.

For instance, the heading tags <h1> through <h6> indicates the enclosed text is a heading, and the heading level communicates the hierarchical structure of the contents of the page. This is semantic because browsers know how to render them and presentational because readers know what headings are. On the other hand, the <b> tag is only presentational because it defines how text should look, but does not convey additional meaning.

Semantic HTML is the foundation of an accessible website. For example, screen readers provide alternative ways of navigating the page, so users can jump between different types of content like links, forms, headings, lists, and paragraphs. This wouldn’t work if divs and spans were used instead, as they are explicitly designed to not convey any meaning.

Using semantic HTML is also a software engineering best practice. It makes development easier by resulting in more readable source, leveraging built-in functionality browsers provide for many elements and simplifying selectors.

Expertise in the correct use of HTML are often not valued or appreciated. Even though HTML is the building blocks of the web, many introductory online materials and university courses don’t spend enough time teaching it in detail. Instead, they promote the misuse of divs and spans, attaching classes like button for styling and adding JavaScript to mimic the functionality of built-in elements. This is the root cause of many inaccessible websites.

Use Native HTML Whenever Possible

Use built-in HTML elements such as <a>, <button> and <select> for interactivity. This increases accessibility and leverages the built-in behaviour provided by browsers. Try navigating with a keyboard on this example webpage with some buttons, a select and some form fields.

Many sites use scripted divs and spans to replicate the functionality of native HTML elements. Unfortunately, they typically only account for use with a mouse and such controls are almost always inaccessible. While it is possible to do so correctly, it is easier to use normal HTML. See this example on replicating a button with a div for why this should be avoided.

Note that using scripted divs is not always bad - doing so is necessary when implementing widgets not built into HTML.

Use Headings to Create Logical Structure

Headings should be used to create a logical outline of the page. Good heading structure makes it easier for search engines and screen reader users to understand a web page.

The content under a <h1> should represent the main content of the page, subsections marked with <h2>, subsubsections with <h3> and so on. A heading’s level should never increase by more than 1. For example, using a <h2> followed by an <h4>. The subsections of this article are also marked with various heading tags, which is used to automatically generate the table of contents.

You can use the a11y-outline extension to visualize the heading structure of a web page.

Watch out for these antipatterns:

An <a> element without a valid href is not a valid hyperlink. Hence, browsers exclude them from tab order, making them inaccessible as they can’t be activated via the keyboard. The default blue underline will also not be automatically applied for invalid links.

Code like <a onclick="...">my link</a> where script that performs the navigation is run on the onClick is very common, especially in Single Page Applications (SPAs).

This is usually caused by the following:

Invalid links without hrefs can still be made accessible by replicating the lost keyboard functionality that browsers provide, but this should only be a last resort:

For more on using links effectively, see WebAIM’s page on Links.

Programatically Label Form Elements

Associate labels with form elements like text fields, radio buttons, check boxes and buttons. This is usually done with the <label> element and the for attribute:

<label for="firstname">First name:</label>
<input type="text" name="firstname" id="firstname" />

When a form field’s purpose can be identified by visual cues so a visible label would be redundant, the aria-label attribute or a visually hidden <label> should be provided for screen reader and voice input users.

The <label> element can also be used as a container to label its form field:

  First name:
  <input type="text" name="firstname" />

Browsers allow clicking the label to select its corresponding field, which is especially useful on mobile devices with smaller screens. Correctly labelling form elements provides a better experience for voice input users, so that commands like “click first name” work correctly. Labelling forms makes it much easier for password managers to autofill them accurately, since they don’t have to resort to heuristics to figure out which field corresponds to which information is requested. Similarly, screen reader users also need to guess what label text is associated to which control when fields are not properly labelled.

Use the HTML5 Sectioning Elements

We use layout, spacing and colour to visually separate web pages into distinct sections such as a navigation bar, the main contents, supplementary asides and a footer with copyright information.

Replacing the use of the <div> container with semantic sectioning elements introduced in HTML 5 makes these relationships visible when not rendered visually. Screen readers present this information so their users can immediately comprehend the overall layout of the website, and move quickly to a particular section. Many other types of software rely on semantic sectioning elements to find and interpret the main contents of a page. Examples include search engines, read it later services like Pocket, Watch OS 5’s display of web pages and the reader mode in browsers.

You can also use the a11y-outline extension to visualize the structure created by sectioning elements on a web page.

The most common sectioning elements include:

Here is how these elements would be used on a typical site.

  <!-- instead of using divs to contain each section, use the following instead -->
    <!-- logo, title etc -->
      <!-- navigation links here -->
    <!-- main site contents -->
    <!-- copyright and legal info -->

Use <table> For Tabular Content

Use the <table> element for tabular content. This makes it easier for software to interpret the data.

Screen readers rely on well structured tables heavily to provide a good reading experience. They provide specialized hotkeys for users to navigate by cell, move to the next or previous row and column, which mimics visually scanning horizontally or vertically. Using the <th> element for column headers causes announcements of the name of the column being moved to, which is equivalent to visually scanning upwards to check its title.

Avoid nesting tables within tables, as it is more difficult for software to parse and for users to understand.

Do not misuse <table> for visual layout. Use CSS instead because this is what CSS is designed for. Unfortunately, tables are often misused in emails for layout. This results in poor HTML which don’t render well in some email clients. It also causes screen readers to attempt to interpret the entire email as a data table, making it challenging for their users to read such emails. Listen to the audio embeds on Litmus’s blog post to experience how difficult it is to read emails with bad markup compared to one with clean HTML.

Besides tabular data, information that is spread across 2 axes should use the <table> element with styling to remove unwanted cell boarders if needed. The display of threads in a forum typically has the thread’s title, its author, the number of posted replies and when the last reply was posted. If divs were used for each cell, it prevents efficient navigation scenarios for screen reader users like scanning downwards to rapidly see the titles of new threads or moving to the next column of information.

Test With a Keyboard

Test your website with a keyboard..

Keyboard accessibility is one of the most important aspects of web accessibility because many users rely on a keyboard. Filling out forms is often faster with a keyboard. Screen reader users typically interact with websites using the keyboard alone. Users who find it difficult to perform fine motor movements use the keyboard. Some users use voice input software or hardware like an assistive switch which mimics the functionality of a keyboard.

Use the tab and shift+tab keys to move between elements on the page, enter to activate controls and the arrow keys to move focus between elements in a composite widget like the nodes in a tree view3. Watch out for the following:

Use Automated Testing To Catch Common Issues

Automated accessibility testing can highlight certain types of issues such as missing alt text in images, insufficient colour contrast, unlabelled form fields or incorrect heading structure. It is scalable, quick to run and can draw attention to problematic parts of a site.

However, automated testing can only discover up to 40% of accessibility issues. It is possible for a site to perfectly pass automated tests while actually being completely unuseable4. Automated testing also cannot assess the appropriateness of the alt text set on an image, find controls that only appear on mouse hover, flag a pseudo table built via divs that should be replaced with an actual <table> element or determine if a custom widget is actually easy to use in practice. Hence, it should be used together with actual manual tests.

There are many automated testing tools available. I recommend starting with the Axe extension or Lighthouse’s accessibility audits. Lighthouse uses the Axe engine for accessibility auditing and is built into Chrome’s dev tools.

Test With Actual Software And Users

To ensure your websites work well, test on various browsers, devices and assistive technologies. This will expose many problems that won’t show up in automated tests.

Start first by testing with a keyboard, followed by a screen reader. Screen reader testing allows you to evaluate your websites from an entirely different perspective. Because of their use of semantic markup, testing with screen readers catches problems that would have been hard to spot visually. For instance, checking if reading order makes sense, labels on form elements, heading structure, table markup and assessing the accuracy of alt text in images.

If you’ve never used a screen reader before, it will be frustrating at first, and you may even mistakenly think your site is inaccessible because you aren’t using it correctly. Here are some guides to using the NVDA screen reader on Windows, VoiceOver built into the Mac and screen readers built into iOS and Android devices. Note that with the exception of NVDA, the other screen readers are built in and don’t need to be installed.

Include users of various types of software and hardware in usability testing. For example, users of screen readers, magnification software, voice input or a switch. This provide valuable feedback about how people actually use your site, and ensures it is not just accessible but easy to use for everyone.

Evaluate Accessibility of Third-Party Dependencies Before Use

When deciding whether to use a third-party dependency for a UI component, ensure that it is already accessible. This is critical because it is much harder to replace a dependency or try to fix it later, especially if it is a complex widget or is used for core functionality on your site.

Even if it claims to be accessible, actually do some testing yourself first to verify its accessibility. Consult the Aria 1.1 Practices Guide for expected behaviour. Ensure that they also meet this checklist of basic custom control requirements. Also apply this process on existing or new reuseable components in your application, since accessible components make it easier to build accessible applications.

Look through issues that other users of the library have reported. If reported accessibility issues are not addressed in a timely fashion, use a different one instead5.


Developing content that is universal to all users allows for more access, more exposure, and more dialogue. We should empathize with everyone who uses the internet, and we should design our web content to optimize for as much access as possible. The guidelines and examples above are just the first steps towards making this a reality.

Using semantic HTML is both an accessibility and software engineering best practice. It enriches web content with meaning, enabling the presentation of information in alternate formats to suit users, automated search engine crawlers and other programs. Using semantic HTML also avoids reimplementing built-in elements, an instance of code reuse and the “Don’t repeat yourself” software engineering principle.

In the future, I will be writing in greater detail to explore topics such as applying these principles in the context of React applications, understanding the accessibility tree and building accessible custom widgets. Thank you for reading!


I’m very grateful to Joseph Goh, Ziwei Ang and my colleagues on the MyCareersFuture team at GovTech for their support and insightful suggestions. I’d also like to thank Jordan Lee for his expert editorial support and writing advice.


  1. This is a recorded Smashing Magazine webinar that I highly recommend watching in full. The link above will start playing at the point where the screen reader usage demonstration starts.

  2. Native HTML elements are keyboard compatible by default. Despite its name, the onClick handler is also invoked when such elements are keyboard activated.

  3. When testing websites using a keyboard with Safari on the Mac, you must first enable the following setting: System Preferences > Keyboard > Shortcuts > Full Keyboard Access : All controls. I’m not sure why Apple disables this by default.

  4. Granted, this is an extreme example, but the point stands.

  5. This applies to all types of issues, not just accessibility related ones. If there are many open issues, then check that the library is at least updated regularly to fix the most important problems.