Common accessibility issues that you can fix today

This week, WebAIM published their latest “WebAIM Million” report. It details accessibility issues they found when they tested the web's top million websites automatically. What is some low hanging fruit you could fix today?

For context, WebAIM, a non profit based out of Utah in the US, have done their ‘WebAIM Million’ project since 2019. They post an extensive analysis every year, looking at trends and improvements/decline in web accessibility over time. I find these posts very insightful and use them to inform my own workshops and outreach. It’s definitely recommended reading!

There are some caveats to be added with surveys based on automated accessibility testing. One is that ‘ease of detectability’ does not correlate with ‘impact on end users’. There are issues that are easy to detect and issues that impact end users most, these are not necessarily the same. Automated tests also cover only a small part of all accessibility, as some things aren’t detectable by machines (yet, or ever). I’m not suggesting this makes the survey less useful or good, but wanted to call it out explicitly. The ACT-Rules Community Group at the W3C works on harmonising test rules for things that are testable.

Ok, let’s look at the top issues and how developers, browsers and CMSes can take away barriers today. Some of these include ideas about what users can do (important caveat: none of this should be user responsibility, website owners should not expect users to use or know about these tools).

Low text contrast

There are cases where text colour and the background colour have a ratio lower than the threshold in WCAG (see also MDN on contrast).

Designers can check contrast manually install plugins (using a tool like Contrast Ratio) or install a plugin like Stark for Figma or Sketch.

Developers can use an automated contrast checker to make sure you avoid low contrast text. Run a checker like the one in Firefox Dev Tools Accessibility Panel or axe in CI/CD, or paste two colours into a manual tool like Contrast Ratio.

Designers and developers alike can use Polypane’s contrast checker that suggests accessible alternatives, which makes it a lot easier to not just find the issue, but also fix it while you’re at it.

Users could use a plugin like Fix Contrast to not be affected: it tweaks colours on the fly so that you don’t have to suffer low contrast text.

There are some discussions on new colour contrast algorithms for WCAG, but this is still under discussion and not ready any time soon.

Missing alternative text

When you create content, describe your images. In your CMS, on Twitter and even in GitHub issues: use that alternative text feature, so that users who can’t see the image can access the content in them. On platforms that don’t support alternative text, like Slack or mobile LinkedIn (!), you can describe images in text. If you choose a CMS or content platform, ensure it can handle alternative text or set it up to do so.

In the resulting HTML, you’ll want something like:

<!-- image with text -->
<img src="website-logo.png" alt="" />

<!-- image with redundant content -->
<img src="hidde.png" alt="" /> 
<p>Photo of Hidde</p>

You can make your decisions on alternative text using the Alt Decision Tree, but basically the gist is that if you were to replace your image with a square, what would you write in the square for it to still be useful? Leaving it empty is an option if that’s the most useful alternative for the image. Like in the example above, there is a photo with a paragraph underneath that describes it. In this case, writing “Hidde” or “Photo of Hidde” in the alt attribute is redundant, it would be best to use an empty alt (but do leave the attribute in there, or some browsers will use the image URL as an alternative).

Users can use Microsoft Edge, which fills in missing alternatives. AI aren’t very good at intentions or context, but pretty much perfect at recognising text. Next time a news website posts an image of new covid rules with no alternatives (as the main Dutch news website used to do throughout the pandemic), users of Edge can follow along.

Empty links and buttons

When links, buttons or other interactive elements don’t have names, assistive technologies like screenreaders or voice controls have no way to uniquely refer to them. If it is to be interacted with, it needs a name.

Imagine the difference between a screenreader saying “here's 4 buttons: button, button, button and button”, versus “here's 4 buttons: publish content, delete content, change to draft, upload image”. In the first instance, you'd need to press them before you know what they do, in the second, it is clear what you're in for, with no further context needed.

Names are derived from text content, like the actual text that’s inside a button, or can be added through an attribute. See Naming things to improve accessibility for more detail or the spec that defines how controls get their names.

Developers need to ensure all controls they build (links, buttons, form fields, etc) have names, ideally that make sense out of context:

<!-- names that make sense out of context -->
<button>Submit form</button>
<button>Publish content</button>
<button>Expand filters</button>
<a href="//">Wikipedia</a>
<a href="//">Hidde on Twitter</a>

<!-- names that are confusing -->
<a href="/">click here</a><!-- avoid -->
<a href="/">read more</a><!-- avoid -->

<!-- names that are missing; avoid or add a name -->
<a href="//"><svg/></a><!-- avoid -->
<a href="//"><img src="" alt="" /></a><!-- avoid -->
<button><img/><button><!-- avoid -->

Browsers can sometimes derive names from nearby text, some do this when there is no text to derive a name from. This is not ideal, can lead to wrong and confusing guesses and be bad end user experience. The developer of this control will know best what the thing does and therefore how it should be named.

Missing form labels

Form labels kind of fall under naming things, as they name form elements specifically.

Developers can fix this by ensuring form fields have a <label> element of which the for attribute points to the id of the input/select/textarea , this also makes that clicking label moves the cursor to the input:

<!-- “for” and “id” are same, this connects them -->
<label for="field">Address</label>
<input id="field" />

They can also add an aria-label attribute to the input to name it that way (but be careful, ARIA labels don’t get translated well).

Missing languages

Proper language indication can get you a Pass on two (!) WCAG Success Criteria (3.1.1 and 3.1.2), and you only need to know one attribute for it.

Developers should ensure the <html> element has a lang attribute with the right language:

<!-- marks this document as 'in English -->
<html lang="en">

Sometimes this is forgotten as the <html> element lives in some template you never touch, but it’s not hard to do, so always double check that this attribute exists and is set to the right language.

If there is content on part the page that is in another language, mark that too, again, with a lang attribute on the relevant DOM node. When you pick a plugin for internationalisation, ensure it sets the lang s or makes it easy for you to do so.

CMSes can make sure that lang attributes are set and set correctly. Browsers can guess languages, but they aren’t always good at this, specifically when it comes to distinguishing dialects: they often matter a lot to people, less so to machines.

Wrapping up

These are some tips based on the most common issues that WebAIM Million 2022 identified. Let’s all put in the work to make sure we, our colleagues, our clients and our users avoid these issues. Like, actually. We need WCAG auditors to focus on higher hanging fruit, by fixing the lower hanging stuff for good.

If this is all new to you, hi, thanks for reading! I hope this helps and feel free to get in touch with questions. If you already knew all of this, please keep spreading the word, so that in next year’s survey, we’ll see steady improvements for the web at large.

Want to learn more about fixing low hanging fruit accessibility issues? In response to the same survey, Christian Heilmann blogged about how to fix accessibility issues using your browser

Comments, likes & shares (95)

Just read: "Common accessibility issues that you can fix today"…
📝 Common accessibility issues that you can fix today 🔗… #html #css #javascript #webdev
Common accessibility issues that you can fix today |…
Common accessibility issues that you can fix today |…
Another good one! Common accessibility issues that you can fix today. #a11y…
Hmm, it's just a common a11y issue that you can fix it by NOW, yes NOW…
Common accessibility issues that you can fix today:… #accessibility #a11y
Common accessibility issues that you can fix today… #webdev #a11y
Common accessibility issues that you can fix today, by @hdv…
"Common accessibility issues that you can fix today" ...…



WebAIM,是一家总部位于美国犹他州的非营利组织。自2019年,启动WebAIM Million’项目。每年发布综合分析报告,观察互联网可用性的发展趋势和改善/下降。


一是“易于感知的问题”和“对用户造成影响的问题”,两者无关,是不一样的。自动化测试也只涵盖了所有互联网可用性中的一小部分,因为有些问题机器(现在或永远)无法检测。我并不是说这会降低调查的作用,而是想明确指出这一点。W3C的ACT-Rules 组织致力于指定合理的测试规则。

好的,让我们看看当今最热门的问题以及开发人员、浏览器和 CMS 是如何解决问题的。


在某些情况下,文本颜色和背景颜色的对比度低于WCAG阈值(另请参见MDN on contrast)。

通过安装插件(如:Contrast Ratio 设计师可以检查对比度。

开发人员可以使用自动对比度检查器,来确保避免使用低对比度文本。运行一个检查器,如Firefox 开发工具辅助功能面板中的检查器或CI/CD 的ax,或者将两种颜色粘贴到一个手动工具中,如 Contrast Ratio。

设计人员和开发人员都可以使用 Polypane 的对比度检查器,它会给出替代方案建议,这不仅可以更轻松地找到问题,还可以同时修复问题。

用户可以使用像Fix Contrast这样的插件:它可以即时微调颜色,这样就不必忍受低对比度文本。



当你创建内容,对图片进行描述。在使用Twitter的内容管理器,甚至在GitHub上发布帖子:使用替代文本功能,以便看不到图像的用户可以访问图片的替代文本。在不支持替代文本的平台上,例如 Slack 或移动 LinkedIn (!),可以用文本描述图像。如果您选择 CMS 或内容平台,确保它可以处理或设置使用替代文本。

生成的 HTML 如下:

<!-- image with text -->
<img src="website-logo.png" alt="" />

<!-- image with redundant content -->
<img src="hidde.png" alt="" /> 
<p>Photo of Hidde</p>

你可根据Alt Decision Tree书写替代文本。文本内容的要点是,如果图像的位置显示出一个正方形,在正方形中写什么以使其不影响阅读?可以选择将其留空。就像上面的例子一样,有一张照片,下面有一段描述它的段落。在这种情况下,在alt属性中写“Hidde”或“Hidde 的照片”是多余的,最好使用一个空的alt(但不要将属性保留在那里,否则某些浏览器会使用图像 URL 作为替代)。

用户可以使用 Microsoft Edge,它可以填补缺失的替代文本。AI 不擅长理解意图或背景,但精通识别文本。下次新闻网站再发布新冠病毒防治新规则的图片,并不带有替代文本时(就像荷兰主要新闻网站在整个疫情期间所做的那样),Edge 的用户可以理解其内容。



屏幕阅读器说“这里有 4 个按钮:按钮、按钮、按钮和按钮”与“这里有 4 个按钮:发布内容、删除内容、更改为草稿、上传图像”,想象一下两者之间的区别。在第一种情况下,需要按一下按钮才知道按钮的用处;在第二种情况下,不需要任何额外操作。



<!-- names that make sense out of context -->
<button>Submit form</button>
<button>Publish content</button>
<button>Expand filters</button>
<a href="//">Wikipedia</a>
<a href="//">Hidde on Twitter</a>

<!-- names that are confusing -->
<a href="/">click here</a><!-- avoid -->
<a href="/">read more</a><!-- avoid -->

<!-- names that are missing; avoid or add a name -->
<a href="//"><svg/></a><!-- avoid -->
<a href="//"><img src="" alt="" /></a><!-- avoid -->
<button><img/><button><!-- avoid -->





<!-- “for” and “id” are same, this connects them -->
<label for="field">Address</label>
<input id="field" />

他们还可以给输入框添加一个aria-label属性(注意,ARIA 标签解析得不好)。


开发人员应确保元素具有 lang 属性,并使用正确语言:

<!-- marks this document as 'in English -->
<html lang="en">

有时有忘记,因为<html> 元素存在于哪些从未修改过的模板中,但这并不难,因此请务必仔细检查此属性是否存在并设置为正确的语言。

如果页面的一部分内容是另一种语言的,在相应DOM节点元素上再次设置lang属性。当使用国际化的插件时,确保设置了 langs 。

CMS可以确保 lang 属性的正确设置。浏览器可以猜测语言,但也有可能出错,特别是在区分方言时:它们通常对人很重要,而对机器则不那么重要。


Common accessibility issues that you can fix today |…
Common accessibility issues that you can fix today… #NAGWGoodies
Appreciate this succinct #accessibility checklist from @hdv with links to plugins for designers. 👏…
#Accessibility Common accessibility issues that you can fix today…
Interesting article on findings from a @webaim report on trends and improvements/decline in web accessibility over time. What common accessibility issues can you fix today?…
Does your #website follow #accessibility standards? Check out these common accessibility issues that can be fixed right now! @hdv #design…
"Common accessibility issues that you can fix today" ➡️… #Accessibility #Frontend #WebDevelopment
"Common accessibility issues that you can fix today” (via @hdv) #a11y Part 1:… Part 2:…

@omgmog lol what a coincidence, I just finished reading both articles! One of the points in the focus paragraph made me realize I have to move my hidden rel="me" links: they are present when pressing Tab, but they don't have focus in the page and it's confusing...

thanks Hidde for sharing!
Want to address accessibility issues on your website? Try these easy-to-implement solutions 👇…
Common accessibility issues that you can fix today…
Common accessibility issues that you can fix today…

The WebAIM Million report presents a sad state of where the top one million websites on the web from an accessibility perspective. Even if you’re not working on a top one million website, the lessons we can learn from the report are worth it.

In the table below, we see the most common accessibility issues and what percentage of the top one million websites exhibit the issue.

WCAG Failure Type % of home pages in 2022 % of home pages in 2021 % of home pages in 2020 % of home pages in 2019 Low contrast text 83.9% 86.4% 86.3% 85.3% Missing alternative text for images 55.4% 60.6% 66.0% 68.0% Empty links 50.1% 51.3% 59.9% 58.1% Missing form input labels 46.1% 54.4% 53.8% 52.8% Empty buttons 27.2% 26.9% 28.7% 25.0% Missing document language 22.3% 28.9% 28.0% 33.1%

To me this is appalling. These are not complicated things to fix or automate a solution for.

This post will look at some of the problems and how to fix them manually. In a future post, we’ll look at tooling to automate a11y testing.

Manual fixes

The manual fixes require working with CSS and HTML. It also requires external tools and built-in browser developer tools.

Low contrast text

The problem is that the lower contrast the harder it is to read. This is mostly a design decision… developers have less influence in the design of a page or app than designers do.

That said we can manually check the contrast of foreground over background text using tools like the Contrast Checker or Deque’s Deque Color Contrast Analyzer.

The goal is to reach the following levels under the following conditions:

Specification Level Normal Text Large Text WCAG 2.0 AA 4.5:1 3:1 WCAG 2.0 AAA 7:1 3:1 WCAG 2.1 AA 4.5:1 3:1 WCAG 2.1 AAA 7:1 4.5:1

WCAG 2.1 AAA requires a contrast level of 3:1 for graphics and user interface components such as form input borders.

Large text is defined as 14 point (typically 18.66px) and bold or larger, or 18 point (typically 24px) or larger.

You can extract colors from the page you’re viewing using extensions like Colorzilla (available for Chrome and Firefox).

Since version 89, Chrome has a different algorithm for calculating contrast. In New color contrast calculation – Advanced Perceptual Contrast Algorithm (APCA) (part of what’s new in DevTools for Chrome 89), the DevTools team explains what APCA is and how it works.

Since this is an experimental feature, I would hold off on using it until it’s available in other browsers or becomes part of WCAG 3.0 or later.

Missing alternative text for images

This one is another low-hanging fruit that can easily be fixed manually just by being careful.

When writing the code for an image, whether it’s a standalone figure or a responsive image with multiple srcsets, add the alt attribute to the image, whether it’s the default image for a responsive set or a standalone image.

    alt="View of the mountains from the northern part of Santiago, Chile" >

The following responsive image shows the inclusion of the alt attribute as a normal image would:

<img srcset="safari-photo-480w.jpg 480w,
             safari-photo-800w.jpg 800w"
     sizes="(max-width: 600px) 480px, 800px"
     alt="Safari photo of a male lion approaching">

This is as easy as it gets. There is no excuse why we can’t add this when adding the tags, if we’re writing HTML or templates for our CMS content, or when entering data into a CMS.

TO check that the alt attribute is present, you can do a global search for the images on the page and check that the alt attribute is present and has a meaningful value.

If you use figure elements with the optional figcaption child, you should still use the alt attribute in the img child. Figure and figcaption – extended alternate text for screen readers? shows how different screen readers handle the figcaption attribute. the TL;DR is that the figcaption attribute is not a substitute for the alt attribute.

Empty links

A lot of times when I see a link with no text, either because the author forgot it or because it includes an icon or an image like a social media icon.

<a href="" id="myLink"></a>



The problem with this is that screen readers and assistive technologies don’t have a way to derive context from the link alone. They use the content of the alt attribute as the content that they’ll show the user.

According to Hidde de Vries:

If you were to replace your image with a square, what would you write in the square for it to still be useful?

Source: Common accessibility issues that you can fix today

Leaving it empty is an option if that’s the most useful alternative for the image.

Missing form input labels

39% of the 4.4 million form inputs identified were not properly labeled either via <label> child element, aria-label, aria-labelledby, or title.

<form action="" method="get">
  <div class="form-example">
    <label for="name">
      Enter your name:
    <input type="text"
  <div class="form-example">
    <label for="email">
      Enter your email:
    <input type="email" 
  <div class="form-example">
    <input type="submit"    

To me, this is just a design and development decision. You should make this part of your reviews: all form fields should have a label and indicate what element the labels are intended for.

We can also use aria-label to indicate the label for the form element or aria-labelledby to indicate the element that describes the form element.


The number of headings and the sequence of headings matter.

Headings are the primary mechanism used by screen reader users to navigate content so their proper implementation is important.

According to the WebAIM

19.6% of home pages had more than one <h1> – an increase from 18.4% in 2021. There were 1,092,097 instances of skipped heading levels (e.g., jumping from <h2> to <h4>) and 1 in every 21 headings was improperly structured. Skipped headings were present on 40.4% of all pages (up from 38.4% in 2021), and 9.9% of pages had no headings present at all (down from 10.6% in 2021).

Source: WebAIM One Million

Here are a few tips on how to use headings in an accessible way.

  • Only use one <h1> element per page. This will usually be the site title
  • Use headings sequentially. If the first element is a <h1> it’s children should be <h2>, its children should be a <h3> and so on
  • Don’t skip levels. Don’t go from <h2 to <h4>. Use the sequence as it was intended

Empty buttons

Just like links, not having content between the button opening and closing tags hurts accessibility. By default, a button’s accessible name is the content between the opening and closing <button> tags so not having any content or having content that can’t be read by assistive technology makes the button inaccessible.

Even though this button is perfectly usable as a search button for abled users, it won’t work with screen readers.

<button type="submit">
   <svg id="search" viewBox="0 0 16 16.9">
      <path d="M16, 15.7L11.3,11C12.4,9.8,13, 8.2,13,6.5C13"></path>

The first way to fix this is to save the SVG as an image and load it like a typical image with an alt attribute.

<button type="submit">
   <img src="/search-icon.svg" alt="Search"/>

Depending on what your SVG does, it may not work in browsers.

If this is the case then the second option is to keep it as an inline SVG and modify it with accessibility attributes.

We add aria-describedby to the SVG element pointing to the element that describes the button, search in this case.

Then, we add the title element as a child of SVG and with an ID attribute that matches the name we used in the aria-describedby attribute of the parent SVG element.

<button type="submit">
  <svg id="search" role="img" aria-describedby="searchIcon" viewBox="0 0 16 16.9">
    <title id="searchIcon">Search</title>
    <path d="M16, 15.7L11.3,11C12.4,9.8,13, 8.2,13,6.5C13"></path>

You can read about possible strategies and really go in-depth on proper markup in images and SVG graphics in Contextually Marking up accessible images and SVGs by Scott O’Hara.

Naming things to improve accessibility gives pointers on how to name things to make them more accessible.

Accessible Name and Description Computation 1.1 is the specification that explains how browsers compute the accessible name and description of elements.

Missing document language

This one was interesting to me. The html root element needs to have a language attribute.

Unless it’s overridden. Setting the lang attribute in the html element will set the default language for the page.

<html lang="en">

This will help screen readers load language-appropriate pronunciation and other rules that will help present content in different languages.

If a page uses multiple languages you can set the lang attribute for each part that uses a different language.

<html lang="en">
    <title>My Page</title>
    <h1>Hello World</h1>

    <aside lang="es">
      <h2>Información para hispanohablantes</h2>

    <aside lang="fr">
      <h2>Informations pour les francophones</h2>

Links and resources

Common accessibility issues that you can fix today…
Common accessibility issues that you can fix today:… by @hdv #a11y #webdev