Debunking the Myth: Accessibility and React

Mark Steadman from Deque:

React can be an accessible application framework with the right knowledge and the right know-how. The stigma that it is not an accessible framework is simply not true. It has some of the best built-in accessibility functionality there is out there, and a large community of accessibility advocates that are creating content that is easily consumable in your application.

As Chris Coyier said it:

React didn’t use a <div> for a <button>, you did. React didn’t force extra markup all over the page when you decided to not use a Fragment. React didn’t forget to change the title of the page because that was something you neglected.

Yes! Yes! Yes! … A thousand times YES!

I see many (new) devs enter the JS game to just start throwing things around, totally unaware of (or even worse: neglecting) the foundation layers which JS enriches: HTML and CSS. It all starts with HTML and semantics — many unfortunately tend to forget this.

With a huge chance of sounding like a skipping record regarding this: go read Jeremy Keith’s post “Robustness and least power”. In said post he quotes Derek Featherstone who said:

In the web front-end stack — HTML, CSS, JS, and ARIA — if you can solve a problem with a simpler solution lower in the stack, you should. It’s less fragile, more foolproof, and just works.

Data attributes & progressive enhancement by Derek Featherstone

Embrace the platform, folks.

Debunking the Myth: Accessibility and React →

Why <details> is Not an Accordion

Dave Rupert on why that (wonderful) way of Using the <details> element to create modals and menus is not good for semantics.

Because <summary> has role="button", it eats the semantic content of elements inside it.

So that big <h1> inside of your <summary> becomes just another piece of text, sans semantics.

I especially like this part of his post too:

At the risk of being a broken record; HTML really needs <accordion>, <tabs>, <dialog>, <dropdown>, and <tooltip> elements. Not more “low-level primitives” but good ol’ fashioned, difficult-to-get-consensus-on elements. A new set of accessible controls for a modern era…

Why <details> is Not an Accordion →

💁‍♂️ FYI: We already have a <dialog> element, as detailed here. At the time of writing it is supported in Chrome (by default) and in Firefox (behind a flag). A polyfill is available.

Making a Better Custom Select Element

24ways – the advent calendar for web geeks – is back! First post is “Making a Better Custom Select Element” in which Julie Grundy tries to create an accessible Custom Select Element:

Sometimes, I can’t recommend the select input. We want a way for someone to choose an item from a list of options, but it’s more complicated than just that. We want autocomplete options. We want to put images in there, not just text. The optgroup element is ugly, hard to style, and not announced by screen readers. The focus styles are low contrast. I had high hopes for the datalist element, but although it works well with screen readers, it’s no good for people with low vision who zoom or use high contrast themes.

Here’s a pen with the result:

Making a Better Custom Select Element →

Indicating focus to improve accessibility

Great article by Hidde. It totally rhymes with my Building Better Forms™ by not taking away affordances post.

It’s a common, but fairly easy-to-fix accessibility issue: lack of indicating focus. In this post I will explain what we mean by focus and show you how focus outlines make your site easier to use.

Indicating focus to improve accessibility →

Accessible Icon Buttons

Sara Soueidan:

An icon button is an icon that triggers some sort of action on the page. More accurately, technically speaking, an icon button is a button that contains an icon and no (visible) accompanying text.

Putting aside the UX side of the coin and whether or not an icon alone is enough to convey meaning and functionality to users, many implementations of these buttons today lack the proper accessibility that makes them meaningful to users of assistive technologies.

Sara gives us 5 techniques to solving this.

Accessible Icon Buttons →

12 Tips for More Accessible React Apps

If you want to improve the accessibility of your React apps but you don’t know how or where to start, this talk is just what you need. Manuel shares 12 tips that will help you build web sites and applications that can be used by anyone. Each tip fits on one slide and you’ll be able to put them into practice right away without having to learn anything fundamentally new. The tips include testing, HTML, JS techniques, and general best practices.

The best tip still is the first one: know your markup. HTML contains the basic building blocks of the web. Use them.

Watch the video (embedded above), or check out the written post.

12 Tips for More Accessible React Apps →

Building Better Forms™ by not taking away affordances

Don’t fiddle too much with your forms‘ look and feel. A small innocent-looking piece of CSS, even when combined with semantically correct HTML, could leave you with a degraded User Experience and make your forms less Accessible.

Yesterday I went to see Girl at Kinepolis. Whilst ordering tickets I ran into an issue though: after completing the payment form – or at least I think I had – it complained about some incomplete fields.

Can you spot the missing completed field(s)?

🤐 Insert sidenote here about the error message not being very distinguishable from the rest of the page, it blends in whilst it should stand out.

After scratching my head for a while, it turned out that I hadn’t selected a payment method. So I selected one, and could continue on forwards.

Oh, those were options for me to choose from!?

🤐 Insert sidenote here about the active payment method indicator being red, which mostly is used to visually indicate errors.

Today, the day after, I revisited the form as I wanted to know why I had missed the payment method in the first place. I work in web, so completing forms shouldn’t be an issue to me, right? I first thought they’d be using some crazy markup/JS combo, but the good thing about this form is that they’ve actually used radio buttons for the payment method selection.

<div class="method-list">
        <label class="method-list-item" data-method-list-item="">
            <input type="radio" name="PaymentMethod" value="BCMC--Ogone--CreditCard" class="method-list-item-input" required="">
            <span class="method-list-item-copy">
                    <img src="" alt="BCMC">
        <label class="method-list-item">
            <input type="radio" name="PaymentMethod" value="MasterCard--Ogone--CreditCard" class="method-list-item-input" required="">
            <span class="method-list-item-copy">
                    <img src="" alt="MasterCard">
        <label class="method-list-item">
            <input type="radio" name="PaymentMethod" value="Visa--Ogone--CreditCard" class="method-list-item-input" required="">
            <span class="method-list-item-copy">
                    <img src="" alt="Visa">
        <label class="method-list-item">
            <input type="radio" name="PaymentMethod" value="Maestro--Ogone--CreditCard" class="method-list-item-input" required="">
            <span class="method-list-item-copy">
                    <img src="" alt="Maestro">
        <label class="method-list-item">
            <input type="radio" name="PaymentMethod" value="MasterPass--Ogone--MasterPass" class="method-list-item-input" required="">
            <span class="method-list-item-copy">
                    <img src="" alt="MasterPass">

Great! As these elements are some of the basic building blocks of the web, they have built-in traits such as having the right semantics, being accessible, etc.

🏆 Extra bonus points for wrapping those inputs in a <label> by the way!

What’s going on then? Well, the “bad” thing about this form is that those radio buttons were visually hidden, as they’d been moved offscreen using a small piece of CSS — a not so uncommon technique:

.method-list-item-input {
    position: absolute;
    left: -99999px;

Even though the form is semantically correct (Yay! 🎉), that little piece of CSS unfortunately introduces two nasty side-effects:

  1. [#UX] Removed Affordance: When completing a form, a user scans for form controls which they need to complete. Since the payment method selector does not seem to contain any form controls, as it looks like a “Hey, here’s some logos of the supported payment methods for ya” kind of thing, the brain skips over it.
  2. [#A11Y] Removed focus indication When tabbing through the form you don’t know that the focus has hit the payment method radio buttons, so you unwillingly skip over it as you keep tabbing. This will give one the impression that they cannot complete the form without the use of a mouse. (It took me a while to figure out how you eventually can: when you’ve hit focus on the payment method selector, hit an arrow key to select one of the options)

Here’s a recording of me tabbing through the form, unknowingly skipping the payment method controls as I didn’t know it got focus:

Now, the fix to these side-effects is quite simple: Don’t try to be smart, and leave the radiobuttons be.

.method-list-item-input {
    /* position: absolute; */
    /* left: -99999px; */

See what I did there?

Sprinkle some CSS on top to make ‘m all a bit more beautiful (alignment, position, color) and you’re good to go:

Ah, these look like options to me!

💁‍♂️ Here’s the CSS I used, in case you were wondering:

.method-list-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    border: 1px solid #bcbcbc;
    margin: 0.25em;
    padding: 0.25em 0.25em 1em 0.25em;

.method-list-item-input {
    /* position: absolute; */
    /* left: -99999px; */
    order: 2;

It adds an outline, adds some margin/padding, and visually moves the radio buttons below the logo (something which I personally find more pleasing). And yes, I know, those logos may be a tad smaller too …

Additionally, they could also add some extra CSS to visually indicate that the wrapping label.method-list-item has a focussed element within. This can be achieved using :focus-within (supported in all modern browsers except Edge):

label.method-list-item:focus-within {
  border-color: #2781a3;

Here’s a recording of me tabbing through the form with all mentioned CSS adjustments applied:

A small change, lifting this form from a 9/10 up to a 10/10, no?

For your own forms, you can use these simple tricks to quickly check them for the issues I just mentioned here:

  1. Tab through your forms (and your site in general) to see if you can access all controls.
  2. Controls should have a different look when they are focussed (e.g. so that you know they have focus)
  3. Think away labels and titles (or translate them to another language), and ask yourself if the meaning of the controls/elements still remain clear or not. (e.g. titles such as “Choose X” don’t indicate choice. Radio buttons / checkboxes / dropdowns do)

Of course those three won’t make a good form all by itself, as you can’t forget about other things the basics such as the use of good labels, grouping of controls, etc. — See Designing Better Forms for a good list of tips.

Here’s to good forms! 🥂

Did this help you out? Like what you see?
Thank me with a coffee.

I don't do this for profit but a small one-time donation would surely put a smile on my face. Thanks!

☕️ Buy me a Coffee (€3)

To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.

Hiding inline SVG icons from screen readers


Roger Johansson:

SVG files may contain a title element which may or may not get announced by screen readers (depending on SVG embedding technique, browser name and version, and screen reader name and version). So far I haven’t run into a situation where I want any other behaviour than screen readers completely ignoring icons (since they are all accompanied by text).

After a bit of testing, I found that simply adding aria-hidden="true" to the svg element solves the problem.

Like so:

<svg aria-hidden="true">
	<use xlink:href="icons.svg#icon" />

Hiding inline SVG icons from screen readers →