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.

That old lady being awesome on the web

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.

Screen Reader Basics: VoiceOver

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 VoiceOver
  • Tab | 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 Headings
  • ctrl + 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.

Demo based on my website with similar issues

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! 🙌

Start by improving Keyboard navigation

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


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:

Help Screen Readers to better understand what you want communicate
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> .

Help Screen Readers how your website content is related
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 and blur
  • +3 attributes on HTML - aria-labelledby , id and aria-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!