Developing with a screen reader opened my eyes
For my last two projects, I proposed to myself to create the most accessible dashboard I could. It should apply correct color contrast, announce navigation changes and among other things, be completely accesible using a screen reader.
So I started to use NVDA, a screen reader for Windows, while I was coding. In the beginning it almost drove me crazy, because it, well... reads everything that is in your screen, so every time I went back to the editor, it would start to read my code. I solved it by simply muting it.
To better use it, I had to start using my keyboard to navigate (something I would only do before if a cat was sleeping over my arm). And this combination of keyboard and screen reader was the turning point.
With my keyboard I could find unreachable places in the UI, places where focus should stay in one place (like an open modal), and fix it. I started to proactively use focus traps to improve navigation after that.
Things I would never "see"
I've created a search input without a label (yellow flag), but put a placeholder
and gave aria-label
a descriptive name. To make it even clearer that that input was a search field, I decided to put a search icon inside it, using SVG. It was beautiful and everybody would understand what that field was about, right? Except for the fact that the screen reader was now reading my input AND the content of the SVG. It would be a mess you somebody was depending on screen reading to understand what was going on. The solution was a simple aria-hidden="true"
in the SVG.
A dead simple solution with a huge impact.
Another example, and this one I think more people would find it familiar: creating tables without actually using a table
.
I've created a complex table layout with what I thought would be a modern stack with a modern look™. Grids to layout cells, div
s, some semantic tags, responsiveness, crème de la crème. Then I unmuted the screen reader. I can still remember the first words of John, the screen reader voice: "Stop doing this shit!".
I had two options: add aria-role
to every element of the table or, guess what, use a real table
.
Why is this so important, you may be asking, and I'll tell you. With normal HTML elements, the screen reader will just read each element as if it was alone, without any context, while with a proper table, as soon as you reach the right element, it would announce: "table with eleven rows and four columns", and start to name each column and five you navigation options.
Nothing is more semantic than the right elements.
I apologized to John, deleted my code and started writing a table
. It took me some time to get it right (I would usually cross the street if I saw a table
coming), but in the end I think the experience is better for everybody.
If you're interested, you can navigate through the dashboard here.
I've also created a React component library with a lot of these rules baked in (and used it to develop the above app) that you could find useful.