The web is awesome and everyone should be able to read it
These last months I’ve been improving my website accessibility so anyone can understand it. Here’s what I’ve learned:
By anyone I mean any person that doesn’t use the internet like I do. Having empathy with the users is one of the things I’ve been learning on web development. You should give it a try as well. Not everyone interacts with an interface or uses the same device and input devices as you do.
Empathy is the capacity to understand or feel what another person is experiencing from within the other person’s frame of reference, i.e., the capacity to place oneself in another’s position. — wikipedia
So you should adapt your product for them. By adapting I don’t mean making it uglier. I mean making it simple. And doing something simple is hard. It’s good to force yourself to rethink your interface or logic in order to accomplish a more complete and intuitive solution.
The problem
I love to explore new interactive ways to communicate a message, so last Summer I rethought my personal website. I don’t consider it a straightforward portfolio, as interaction is the way to explore it. That’s the best part about it and at the same time the worst part.
Some months ago I got to know that users who use only keyboard or screen readers can’t understand shit. They have so many visual and interactive elements to explore that they end up lost. As a web lover, excluding people from using it to its fullest potential, just makes me really sad.
Let me ask you something before you continue:
Go to a website that you built and navigate only with the keyboard. Can you accomplish everything it has to offer?
You can use the Tab
key to jump between interactive elements such as buttons and links. Can you open a menu, modal or any other link and navigate through your gallery? Well, my website failed on some of those points. Now, let’s try the same with a screen reader. Oh wait… I didn’t even know how to use a screen reader.
That was when I decided to make my website more readable by improving its accessibility.
Taking action
Learning how to use Screen Readers
I confess my knowledge about SR (screen readers) was almost inexistent, so I had to start somewhere. This tutorial is about basic navigation on web with VoiceOver for Mac. There is also a tutorial for JAWS and NVDA.
These are the 5 shortcuts I used the most while on a webpage with VoiceOver. With these you are ready to put at test a webpage accessibility:
cmd
+F5
turn on / off the VoiceOverTab
|Shift+Tab
navigation by interactive elements. You can use this even without a Screen Reader.ctrl
+alt
+◀︎ ▶
(arrow keys) navigation by all the content.ctrl
+alt
+cmd
+H
navigation by Headingsctrl
+alt
+U
open Rotor: a menu with different organizations about the page. (Landmarks, Links, Headings, etc…) Use◀︎ ▶
to navigate through them.
Having empathy
While using the VoiceOver on my website, my never-ending list with accessibility problems was growing. Let me share some of them:
- Useless / duplicated DOM elements being readable by SR
- No Landmarks such as header, nav, article, etc…
- Lack of Headings while interacting with the website
- Links without any text (only icons)
- Elements without feedback on :focus, only on :hover
- Lack / lose of context on interactive elements
- Unreachable content at all
- … 😱
Creating a plan
I created the 1% better each day project on Github with all the tasks related to each issue and when I find the time, I’ve been fixing them.
Let’s fix it
Here I’ll share with you how I improved accessibility on Contacts part. To make it simple, I’ll go through a CodePen example similar to my website.
So, this is what you can see:
- There’s 3 contacts shown only with icons.
- The title is ‘Social Networks’ and the description is ‘Not a big fan of Facebook’.
- On
mouseenter
at a icon, the title is replaced by the social network name and the description is related to that same social network. - On
mouseleave
the title and description returns to its original content. - On
:hover
the icon color turns white. - Those text blink effects are CSS animations triggered by Javascript.
Probably you can confirm it all, if you use a cursor like me.
1. Keyboard Navigation
Now, try the same with only a keyboard. No fancy text blink effects, no icon color changed. And an ugly blue outline. 😑 So, before trying Screen Readers, let’s improve the navigation with keyboard first:
The Tab
key triggers :focus
event but the demo is only prepared for :hover
, mouseenter
or mouseleave
events. To fix this, :focus
must have the same behavior as :hover
and mouseenter
. And blur
(focus leave) should have the same behavior as mouseleave
.
I also replaced the blue outline by a flash CSS animation and a white color. Please, never ever remove the :focus
browser default outline without a fallback visual option. It’s always better to have an ugly feedback that none at all!
So, navigation with Keyboard is now fixed! 🙌
2. Screen Reader Navigation
Use your SR and try to navigate again:
🗣 Heading Level 4 — Social Networks
Link [?] (pause) Sandrina’s Codepen
Link [?] (pause) Sandrina’s Github
Link [?] (pause) Sandrina’s Twitter
unknown
😵
Let’s start with the Links. A link without text is a empty action for screen readers. Even if you have a title
attribute, it doesn’t fix the issue because the dictation is not immediate. There is also, associated to the link, a description that should be spelled.
The solution is to associate each link to its name and description. How do we do that? With the use of ARIA. What the heck is that?
Accessible Rich Internet Applications (ARIA) defines ways to make Web […] more accessible to people with disabilities. For example, ARIA enables accessible navigation landmarks, […] form hints and error messages. ARIA is a set of special accessibility attributes which can be added to any markup, but is especially suited to HTML. — Aria — Accessibility | MDN
To connect the link to the title and the description we use the attribute aria-labelledby
on the active element, in our case <a>
, and its value is the id
of the title and description elements.
And the Screen Reader will read:
🗣 Link, Codepen, Because coding without fun is just boring [?]
See that weird [?]
? That’s because SR doesn’t understand content: "\f1cb"
(the icon font-family unicode). We need to hide it from the SR by using the attribute aria-hidden="true"
on the <i>
. This attribute will tell a SR to ignore the element and everything that is inside it.
🗣 Link, Codepen, Because coding without fun is just boring
We are almost done. Now it comes the tricky part:
Remember the unknown
part? Let’s analize another scenario: 1. read the Heading, 2. Go forward to the first contact, 3. return to the previous Heading. This is what happens:
🗣
✓ Heading Level 4 — Social Networks
✓ Link, Codepen, Because coding without fun is just boring
🐛 Heading Level 4 — Codepen
See the problem? When the SR is reading an element, the last focused element stays focused. So, despite the SR reading the Heading (that should be Social Networks), its content is Codepen because its link is still focused. The same issue happens with the description unknown
too. With this I learned two things:
- A Heading content shouldn’t be changed. If at any moment the user decides to access the Headings Menu, at the same moment a contact link is focused, the Social Network heading will display Codepen instead of its real name. This is what is happening to the contact description too.
- Semantic content should be respected and not be despised to satisfy “visual fireworks” . They are both important.
So, to fix this we will create 2 elements: One for semantic purposes and another one for visual purposes.
We create a simple Heading with a class .srOnly
that contains CSS rules used to visually hide an element but still being accessible by SR. Then, the “Heading copy” is only a <span>
because it doesn’t have any semantic purposes. Now it comes the pro tip: Despite hiding an element from the SR using aria-hidden
, the element can still be used as aria-labelledby
target. How awesome is that? Do the same for the description element and everything should work. You can check the changes below. Give it a try:
🗣
Heading Level 4 — Social Networks
Link, Codepen, Because coding without fun is just boring
Link, Github, Sharing it’s what make us better
Link, Twitter, Where geeks share geek’s stuff
Not a big fan of facebook
3. Take advantage of HTML Semantics
So far we already improved a lot the Contacts, but there is one last thing we can improve: These social networks are a list of contacts. That can be understood visually, but for a Screen Reader is just a bunch of links. We can easily improve that by using a <ul>
.
🗣
Heading Level 4 — Social Networks
List 3 items
Link, Codepen, Because coding without fun is just boring, 1 of 3
Link, Github, Sharing it’s what make us better, 2 of 3
Link, Twitter, Where geeks share geek’s stuff, 3 of 3
End of list
Not a big fan of facebook
Now the Screen Reader can be much more explicit and we can better understand how things are related!
Let’s recap what we had change:
- +1 selector on CSS -
:hover
- +1 CSS class -
.srOnly
- +2 events listeners on JS -
focus
andblur
- +3 attributes on HTML -
aria-labelledby
,id
andaria-hidden
- +3 element on HTML - 2x
<span>
and<ul>
And this is all that costs to make an element with an Interface / Interaction different from the usual and at the same accessible by anyone! 🎉
Looking forward
I just started to learn about accessibility, so what I’ve told you might not be 100% accurate. However, I’m always looking for feedback.
I also learned that accessibility is not only about Screen Readers and Keyboard navigation. There are other concerns such as interface (contrast, hierarchy, etc…) and being able to adjust it depending on the device. These are some of the topics I’ve been studying on my website too. If you like this, let me know and I can share with you more topics related to accessibility.
Remember, web is awesome and everyone should be able to feel it! 🙌
Thank you!
P.S. I want to thanks Florian Beijers for his help. He was one of the persons who made me want to learn more about accessibility!