TIL How to Enhance Accessibility - Screen Readers

TIL How to Enhance Accessibility - Screen Readers

While attempting to incorporate drag and drop into my first rails project, I encountered some critical information on how to make websites more accessible. It started with a great article about how to make drag and drop features accessible for keyboard users (source), but it opened me up to a whole world of accessibility features I hadn't learned yet. All I really knew until reading that article and falling into the subsequent documentation rabbit hole, was that you really ought to have alt text in all your img tags.

Drag and Drop

Often drag and drop is implemented in ways that rely on a trackpad or mouse. The typical experience is geared towards a user moving the mouse, clicking on an element, dragging it into its new position and placing it by releasing the button/click. Ideally, users operating with a keyboard would have the same range of experiences accessible to them that a user with a mouse has.

Info Queue

Screen readers often hear text on a first in, first out basis. The information is queued as the user navigates around the web page. ARIA (Accessible, Rich, Internet, Applications) are a tool worth considering in the design process. They allow for jumping the queue in order to make important information available quickly.

HTML Roles are a Promise

From the documentation here, I learned about what separates good ARIA vs bad ARIA, and that bad ARIA is worse than none at all. One of the foundational principles of ARIA accessibility is that a role is a promise. To use their example, the following code implies that the developer has incorporated javascript to appropriately power the div with interactions that allow a keyboard user the experience of a button. If they've failed to do that, it'd be like having a link that promises something very cool but that ultimately goes no where.

 <div role="button">Place Order</div>

ARIA Live Regions

The way they do this is with ARIA live regions (see documentation here), and with the implementation of these very cutely named polite and impolite regions... also off (the default state) which is not cute but is still super important. When your site has dynamic regions that change without requiring a page to reload, often the change is visually noticeable. How do we replicate that experience for users who aren't seeing the page visually?

Polite regions, as you'd expect, wait their turn. Impolite regions cut the queue. Create polite text like this.

<div role="region" id="BookInfo" aria-live="polite">

As the ARIA live region documentation states, it's best to keep things like the dropdown menu polite, as then the user of a screen reader will hear the information when they pause over a menu item. It's pretty easy to imagine how chaotic the experience would be if everything you so much as grazed over were put in a queue and read to you, especially if many things were vying for first priority.

How I plan on Incorporating this into My Project:

Drag and Drop

After implementing my drag and drop feature, I'd like to incorporate an ARIA-live region for my drag and drop feature, as well as the necessary javascript to allow keyboard users to access the drag and drop feature with the space bar and arrow keys. To create assistive text that's accessible to users with a screen reader but that is invisible to the eye, I'd follow the suggestions here and make an assistive text a class with an absolute position and make it tiny and thus invisible.

.assistive-text {
position: absolute;
overflow: hidden;
margin: -1px;
height: 1px;
width: 1px;

As well as an aria-live section with the assistive text class.

<section aria-live="assertive" class="assistive-text"></section>

Linking the above to javascript that places the appropriate text inside the span and clears it to make way for new text.

Live Update

Using the following code on my index.html.erb I link to a second page with the updated story in case somebody else has posted something to the story while another user has been sitting on the same page.

<h2>Welcome To The Wonderful World of This Site Existing</h2>

<script>
  const fetchLatest = function () {
    $('#updated-text-area').load('/contributions/latest');
    setTimeout(fetchLatest, 3000)
  }
  fetchLatest()
</script>

<section class="story-area" id="updated-text-area">
    <% @contributions.each do |contribution| %>
    <p> <%= contribution.story_bit %> </p>
<% end %>
</section>


<section class="story-area" id="text-input">
  <%= form_for @contribution do |f| %>
      <%= f.label "Your turn" %>
      <%= f.text_area :story_bit, :placeholder => "Once upon a time, blah blah blah", class: 'text-field'%>
      <%= f.submit "Post", class: "submit-button" %>    
  <% end %>
</section>

This is the code from latest.html.erb

<% @contributions.each do |contribution| %>
    <p> <%= contribution.story_bit %> </p>
<% end %>

This is so that a user doesn't have to constantly refresh the page to check that somebody has posted something new, which was a problem I encountered when I did a test deployment of my project via ngrok. I wanted to test the user experience and to get feedback as well as some fun seed data from my friends.

My <section class="story-area" id="updated-text-area"> seems like an important place to use an ARIA live region with the right aria-live attribute. An aria-live="polite" seems most appropriate to me, as it's best used for any region that receives updates that are important, but aren't so urgent that they are read rapidly, as regions labelled as aria-live="assertive" are.