How I improved this site for Screen Readers

Today, I updated the homepage to be screen-reader friendly. I feel relieved (a bit) of being a fraudster making a clickbait

I had positioned the site to teach accessibility (a11y). Yet, that page isn't accessible to blind users. Or anyone who listens via Assistive Technologies. How ironic!

Here is an audio of how the banner sounds before the update. Listen. I doubt you'll understand because of the noise.

You must have heard 7 heading-level-one elements. But, I used just one. And God knows, I wasn't asking a question towards the end of the audio. So, why the why?

Anyways, after the update, it sounds clear and understandable. Despite no visuals.

Typography Composition of the Title. With the table of contents at the right
Note on Presentation Tools

The screen reader used for all presentation on this page is NVDA version 2021.03.01. Along with Google Chrome Browser version 99.0.4844.51. These are made on Windows 8.1 OS. If you notice anything odd with another device or app, kindly send me a message on Twitter @toheebdotcom

Actions

How I conveyed the content with no noise

Remember weeds are unwanted plants?
So is noise are unwanted speech.

The characters I used for composition became that unwanted speech. Hence, the noise. The video below shows how the noise came to be for the banner before the update. (You heard the audio earlier.)

Why are the design characters read out?
Reason is, I used CSS pseudo-elements ::before and ::after to insert content into the DOM. Contents meant for presentational purpose. Now, screen readers communicate these CSS contents like HTML content.

As if that's not enough, pseudo-elements in an heading are read out as separate headings. And some design characters like y may be confused as the 3 letter word why. All these noise could go away if I mute them.

We can use the CSS declaration speak: none to avoid screen readers reading out content, but there's little to no support for this.

The best way to hide content from screen readers is to declare aria-hidden="true" on the HTML element.

Since I can't hide the elements I appended the design characters to, I used a new element instead.
While I can insert this content into the HTML element, I preferred via CSS. Because the choice of these characters depends on their content style.

Thus: an empty element with aria-hidden="true" for a pair of characters per content segment.

Illustration of 3 DOM elements. Each element's ::before & ::after pseudo-elements are connected by a line to its composition character on toheeb.com's banner.

This result in clearer communication of the banner since the design characters are not read out. Meaning, no noise.

The video below shows the main content being read out after the screen-reader update. This is the current state of the site.


While this section focused on hiding design characters, there are times we'll need to communicate CSS styles. The next section focus on one such moment.

How I communicated Styles that aid content deliverability

The design style influences the content structure. So, I deemed it necessary to hint screen readers.

Because, the page's header isn't the typical logo + nav menu. Nor is the footer a bunch of links. They looked like the front and back cover of a book respectively. Same as the table of contents.

Moreover, owing to an earlier design feedback, I introduced a Dedication section to emotionally connect with my target audience. And, an Introduction section to buttress the essence of the site.

Hence, like a physical book, I have the following parts:

  1. Front Cover
  2. Front Matter
  3. Back Matter
  4. Back Cover

The Front Matter consists of the Dedication, Introduction, and the Table of Contents. While the Back Matter consists of the Case Studies, and Resources. Along with the Front and Back Cover, they make the homepage.

toheeb.com's homepage divided into regions that imitate the main parts of a book

Visually, I plan to constrain each part by a fixed width and height. And, provide the ability to flip through them like the pages of a book. For now, I demarcated them with an hyphen.

Audially, I marked up these regions with landmark elements and assign the book-region's name as the accessible name. That is...

  1. Banner landmark has the label front cover

  2. Main landmark has the label front matter

  3. A generic landmark has the label back matter

  4. Contentinfo landmark has the label back cover

In addition, I modified the title to include the term Book. This way, the terminologies won't sound strange when screen readers navigate by landmark.

Below is a video highlighting each landmark of toheeb.com.

The simplified HTML for the landmarks look like below.

<body>
<header aria-label="front cover"> <!-- ... --> </header>
<main aria-label="front matter">
<!-- ... -->
<section aria-label="back matter"> <!-- ... --> </section>
</main>
<footer aria-label="back cover"> <!-- ... --> </footer>
</body>

I nested Back Matter inside of Front Matter because both content are the main content of the page. Since Landmarks have flat hierarches, this parent-child relationship will be conveyed as if they were siblings.


Despite my nesting, the document outline says different, as intended. Thanks to the heading & sectioning elements.

How I created the Document Outline

Apart from the landmarks, headings are another way for users to navigate the document. According to this Screen Reader Survey by WebAIM, 67.7% of users surveyed navigate via landmarks compared to 3.2% via headings. Hence, the need for a well-outlined document. Which is also useful for search engine crawlers.

A convention is to use an h1 element for the document's title. And, a rule is to avoid skipping heading levels.

Thus, I started the page with an h1 for the document's title which is the front cover's title. Other book parts start with an h2 heading. Each content category uses an h3 while each featured article is an h4.

The video below shows how HTML5 Outliner outlines the page. Notice that both the dedication and back cover's title are visually hidden. Because, they are visually unnecessary.

How I structured the Content Categories

For the Table of Content, I structured the categories as an ordered list. Even though, it didn't use ordinal values for the design.

At first, I doubted if using a list block for the content category was necessary. I went ahead because the total count of 3 simplifies the learning objectives for the user. This supports the goal of the site.

I chose ol over ul because the order matters. But I don't need numbers as list markers in the design:

Illustration showing ordinal values underneath the non-ordinal markers of the Category List of the Table of Contents on toheeb.com

Now comes a challenge. Removing markers of a list item removes its semantics.

One solution is to use a non-breaking space. Another is to re-instate the list block with role="list" though it is against the first rule of ARIA.

What I did is to replace ::marker pseudo element with a visually hidden ::before counter. No violation of ARIA rule. No need to alter the markup.

Starting with the markup, I used an ol element with an accessible name of content category. Each list item has an element hidden from Screen Readers that contains the nominal value used as list marker.

<ol aria-label="content category">
<li>
<i aria-hidden="true"> <!-- marker --> </i>
</li>
<!-- ... -->
</ol>

To hide ::marker of a list accessibly with only CSS, we'll re-instate the counter using ::before selector that can accept visually hidden styles. (Since ::marker selector has limited CSS declarations that can go within it.)

/* Remove list markers */
li::marker {
content: "";
}

/* Re-instate list markers for screen readers only */
li::before {
content: counter(list-item)

/* Visually Hidden Styles... */
}

Here's a video highlighting how the List Blocks of the Table of Contents are read. When there's no content within a category, the elipsis reads No articles yet. Otherwise, it reads More articles coming soon. (I'm looking forward to having each category with a complete set of articles. 💪)

Now that the table of content sounds good. How easy is it to reach it?

How I improved Reachability to the Dynamic Content

When you take a look at the whole page, the dynamic part is the Table Of Contents (TOC). Other parts are static contents conveying the TOC's value. Upon reading those static contents, your focus changes to getting new content at the TOC. Having to scroll past them, everytime, can piss you off.

Navigating to the TOC is easier for screen readers. The first content you'll hear is a skip link to the table of contents. That's because I included a visually hidden skip-link at the top of the page.

Keyboard users are also 1 tab away to access the skip-link. Since it isn't hidden to a tab's focus.

For touch users, you can swipe fast and hope to stop exactly at the TOC. Or pan slowly across the header, dedication, and introduction till you get there. Same for mouse drag. Both has room for improvement.

One thing though, I can make the skip link visible for everyone. But, to touch & mouse users, that is still a boring repetitive step.

Why?
Upon page load, Screen readers and Keyboard users' interaction starts at the top of the page. But pointing device such as Cursor, or thumb may be at any part of the page. It becomes a boring routine if you have to move the cursor to the skip link – every – single – time.

My first counteraction is to use an accordion for the introduction. This won't remove the headache but makes it easier to get to the TOC. On the flip side, it takes a click to read the contents of the introduction. This is a nice tradeoff considering I want the page to be less pitchy.

How about 99% faster? It is possible if I could avoid the top entirely. Not to delete but jump them automatically. By user's request of course.

The way I did it is to store the user's preference and automate a scroll to the TOC whenever the page loads. I like this.

So, I introduced a settings dialog. Which will be helpful later on for other preferences such as reading theme. This dialog is hidden from screen readers but available to keyboard users.

Challenges

In the introduction section, I used a few idioms to express some thoughts. Being idioms, I marked it up with an i element. But to my surprise, NVDA wouldn't convey the opening and closing of the accordion. Because of certain styles such as italic.

I realised long after some troubleshooting. I wish to cry but knowing that I figured the reason, I stayed indifferent. And left the idioms unmarked.

Resources

Here are resources that helped along the way. Big thanks to the authors.

  • How A Screen Reader User Surfs the Web. A workshop by Leonie Watson for Smashing Magazine. Published on Youtube

  • Fixing List and creating accessible accordions by Scott O'Hara

  • Creating an Accessible Modal by Ire Aderinokun


That's it for this milestone!
However, I'll be sharing my progress on Twitter @toheebdotcom. Join the discussion below.

I still have more clickbaits to resolve though. One at a time.

Till next time, Ò dabó!