Thursday, July 14, 2022
HomeWeb DevelopmentConstructing an accessible glossary in vanilla JavaScript

Constructing an accessible glossary in vanilla JavaScript


Introduction

That is the primary time I’ve written an article like this. Most of my articles are sparked by an concept I’ve, after which I do the analysis to make it work, however this text is impressed by a current mission I performed with the e-learning platform Kognity, who had been keen on offering their customers with a top-notch accessibility expertise when utilizing their platform.

Among the many many elements of the platform that we made accessible was an interactive glossary of phrases from their textbook that was out there as an expandable/collapsible sidebar on their on-line platform. Since we had a extremely good expertise constructing a profitable, accessible resolution, I wish to share it.

The Kognity resolution is written in Vue.js, however as a lot of its performance is restricted to their platform — and since I’d wish to make issues as generic as potential for this publish — I will probably be implementing the same resolution in vanilla JavaScript. It must be simple to transform this implementation for varied different frameworks.

We’ll cowl the next on this publish:

A observe about this text’s screenshots and screenreader utilization

There might be vital variations between screenreaders and browser combos, and lots of the screenshots on this article will present how a screenreader works. I’m totally on a Mac, and due to this fact most of my screenshots will probably be of utilizing VoiceOver throughout Firefox, Chrome, and Safari. Nonetheless, code introduced on this article has been examined with NVDA and Firefox on Home windows. In instances the place there’s a distinction in habits, that distinction is famous.

Because of these vital variations, you could need to think about using an answer like Assistiv Labs for testing as a result of they’ll present VMs with completely different screenreader setups you’ll be able to entry remotely. In any case, it will be a mistake to check this code on only one screenreader/browser mixture due to the large variation of their output and capabilities, and you’ll simply miss issues.

Exploring glossary examples

The Kognity glossary

So, first, let’s take a look at how the Kognity glossary works. Within the following screenshot, you’ll be able to see a part of a Kognity biology textbook and the button to open the glossary within the higher proper hand nook.

The Kognity glossary

While you click on the glossary button, the glossary opens and also you see one thing like the next:

The Kognity glossary when open

You will note some letters within the glossary are grayed out — these are the letters that don’t have any entries related to this specific a part of the textbook. As you’ll be able to see, the letter A has a teal circle round it to point that it’s the chosen letter when the glossary first opens (assuming, in fact, that there are entries underneath A).

There may be some further performance related to this glossary, similar to filtering by textual content enter; I gained’t be implementing comparable performance on this article, however am mentioning it for completeness.

The HBOMax film title glossary

I’m certain you’ve seen one thing like this earlier than: letters within the alphabet are listed out, and clicking one of many letters reveals you some content material associated to the letter. On this case, it’s a glossary, however you see the same UI sample for navigating video choices, for instance right here on HBOMax:

The HBOMax title screen

When you click on one of many letters within the right-hand sidebar, the web page scrolls right down to the primary movie with a title that begins with that letter.

So I assume we are able to agree it’s a standard design, however what’s much less widespread is a well-thought-out, accessible one. We’ll exhibit this a bit extra with this HBOMax instance in a subsequent part.

Making an accessible glossary: The strategy

In essence, accessibility is a UX drawback, and each developer and designer has to make use of their creativeness to grapple with it, similar to they need to do about any use of their software. It doesn’t matter what specific set of skills you might need, that set gained’t match these of all your customers.

This act of creativeness is actually the important thing to creating a fairly accessible software, however observe the caveat. I say moderately accessible to emphasise that, whereas there are elements that will probably be very tough, the programming effort required to make apps accessible is trivial, so long as you might have performed the required work of imagining how the appliance will probably be used within the case the place somebody’s capabilities are maybe diverging from your personal. And sometimes, that vital work of creativeness will not be particularly draining, both!

Constructing our consumer profiles

Let’s first image how customers with completely different, specific units of skills will use the content material and instruments for interacting with the content material in your website. Having a set of consumer profiles might be useful. To construct our glossary, we will think about three distinct profiles, as follows:

Consumer profile 1: Customers who don’t use any assistive units and strategies

This contains those that don’t use assistive units or strategies, however nonetheless may have them or lack some capability that isn’t simply mounted with corrective units. So, except for the one who is totally freed from any issues in anyway, on this class, we are going to put:

We will consider this as our baseline regular consumer.

Consumer profile 2: These with a mobility incapacity

This contains those that completely use the keyboard and tab shortcuts to navigate a website, i.e., these with out the power to make use of a mouse or touchpad.

Consumer profile 3: Those that use a screenreader

There are a variety of people that would possibly match this description. There are those that are capable of see the web page effectively sufficient to work together with out a screenreader, similar to those that have dyslexia or different language processing difficulties, however like to make use of a screenreader for assist. Then, there are individuals with visible difficulties who should not formally blind would possibly nonetheless want to make use of a screenreader to assist them. Lastly, there are these customers who’re blind and completely want a screenreader.

You’ll be able to learn a breakdown of screenreader utilization stats from the ninth WebAim Display Reader Consumer Survey, which was final up to date June 30, 2021.

How do these completely different customers use the identical webpage?

Builders who’re new to testing accessibility points resolve to check how all the pieces works by tabbing by way of it. When you can tab to issues, work together with them, and guarantee they work appropriately, then it’s assumed that the web site is accessible.

It’s actually a requirement for accessibility that every one interactive parts must be reached by the tab key, however it’s a requirement primarily for our customers in group two, since utilizing the tab key’s superb for somebody with mobility points who may also visually course of the content material of the web page.

Nonetheless, customers of screenreaders require different methods to order and course of the contents of the web page, and we must always take into account this in our resolution.

Designing internet rotors for screenreader utilization

Particularly, each screenreader has a strategy to learn helpful elements of the web page individually from the conventional web page order. That is helpful for locating what you need to do on an internet site, and navigating to the elements of the web page that curiosity you.

For example, in VoiceOver, that is known as the net rotor (or simply the rotor). Under is a view of the rotor on Kognity with the glossary closed.

The Form Controls web rotor from VoiceOver on the Kognity site

The very first thing you’ll discover is that there are solely 13 type controls with the glossary button closed. That’s nice! Think about in case you had been interacting with this whereas it was open: there could be 12 buttons, plus 26 buttons for the English alphabet, which totals 38 entries to learn out. That may be a lot! And, within the case of these in consumer group 3 who’ve some sight, they may in fact be capable to use the screenreader ingredient’s view visually.

Why are we making an accessible glossary?

To make sure that individuals could make optimum use of the glossary on our web page, we must always design a workflow that’s wise. If the workflow for interacting with the web page will not be effectively thought-out, our web page won’t be usable.

For example of an implementation with accessibility issues, I’m going to select a bit on HBOMax. I don’t have something towards them (though I hoped for lots extra basic Warner Brothers content material), however I simply bought a membership and I discover these sorts of issues as a result of I’m a developer.

Let’s say we’re on one of many pages with the glossary-style navigation, similar to Comedy Films A–Z. If we’re utilizing VoiceOver and resolve to test the rotor, the rotor may have roughly 38 buttons out there to make use of:

The Form Controls from VoiceOver in the HBOMax app

Solely eight of those buttons have a significant label, or one that offers us an opportunity of understanding what they do. The remainder of them are labeled dimmed button.

A “dimmed button” is VoiceOver’s method of saying {that a} button is at present disabled and never usable by the appliance. You might assume that the dimmed buttons are for navigating the classes by first letter of the film titles, however if you click on to see the titles that begin with that exact letter, you’ll understand this isn’t the case (particularly as a result of it’s unlikely you’d depend the variety of dimmed buttons and understand that there are greater than 26).

You may also assume that the dimmed buttons can’t be interacted with in any respect, however they are often. When you click on the primary dimmed button, then the main focus will probably be set on the primary ingredient within the second row of flicks, and you’ll hear VoiceOver announce “Hyperlink: Journey Time”.

However these buttons are within hyperlink parts. Why a button is inside a hyperlink, I don’t know, as I used to be not a part of the event course of, however I can assume that somebody thought they need to be disabled for screenreaders as a result of they put the aria-disabled="true" attribute on them, with out contemplating what the precise impact of doing so could be on the UX.

Button is disabled inside a link element

Within the screenshot above, you’ll be able to see that the hyperlink to Journey Time is aria-disabled="false" and it wraps a div with function="button" that’s aria-disabled. This reveals up in our checklist of dimmed buttons.

I may also observe, as a result of it’s considerably infuriating, that there’s one other button contained in the hyperlink. This button will not be disabled, however is as a substitute marked with aria-hidden="true", so a screenreader can not work together with it in any respect. What does this button do? It lets you add the media to your favorites checklist.

The hidden button that adds the media to your favorites list

Funnily sufficient, it does have an aria-label that tells you its goal, though actually it ought to say one thing like “Add Journey Time to my checklist”.

Oh, wait — I grew to become so concerned in all the pieces that was mistaken with this little little bit of the UI that I forgot to speak concerning the glossary!

As you’ll be able to see, the dimmed buttons should not the elements of the glossary; as a substitute, they don’t seem to be uncovered as buttons, they’re simply straight-up textual content.

The buttons are just text

When you handle to navigate to that checklist of letters that you would be able to click on, and attain the primary of the entries beginning with the letter you clicked, you’ll hear solely “A,” “B,” “C,” and so forth as you navigate by way of them. Moreover, it doesn’t inform the screenreader consumer that the letters they’re listening to are clickable!

So, briefly, generally it’s useful to see one thing that’s utterly unusable so as to take into account what must be performed to make one thing helpful.

Learn how to construct an accessible glossary

Now that we’ve spent a whole lot of time speaking about why I’m scripting this, and exhibiting examples of fine glossaries and people which can be decidedly unhealthy, I believe it’s time to get into code — that’s to say, we’ll get into the instruments we have to implement what we take into account good.

First, I’m simply going to speak about some very particular elements of the code, after which, as we get into the implementation, we are going to focus on the code general.

Utilizing CSS for screenreader-friendly accessible content material

One factor that just about everybody will want if they’re making an attempt to make any a part of their website accessible is a strategy to expose some content material solely to screenreaders. The very fact is, many issues must be defined to a visually disabled consumer which can be in any other case apparent from a visible context. This text from WebAim goes over varied methods of hiding and exposing content material to screenreaders utilizing CSS.

One apparent factor to notice is that the strategies for exposing content material to screenreaders (however hiding them from different customers) are all hacks. It’s, for my part, unlucky that there’s not an aria-only attribute or the same resolution in order that we don’t have make do with these hacks, because the hack has suboptimal behaviors. For instance, the most typical resolution is to put the screenreader-only content material within the a part of the DOM the place we wish it to be encountered and utilizing CSS to maneuver it out of seen view. This has the facet impact of complicated individuals navigating by way of keyboards as a result of focusable parts will nonetheless be within the navigation stream, however outdoors their view.

All that mentioned, we will probably be utilizing the next CSS, borrowed from the linked WebAim article above, for our screenreader-only class:

.sr-only {
    place:absolute;
    left:-10000px;
    high:auto;
    width:1px;
    top:1px;
    overflow:hidden;
}

Except for that, we are going to make one resolution that goes towards common accessibility suggestions: making a few of our buttons not appear to be buttons.

Why are we doing this? As a result of, pragmatically, that ship has sailed. Individuals need to make buttons appear to be different issues, however we want them to be buttons for his or her accessibility advantages.

Since individuals typically need buttons that don’t appear to be buttons, I’m going to indicate you the way utilizing unstyled buttons can nonetheless be accessible. We won’t use an unstyled button class, however as a substitute apply the next properties to the buttons we won’t be styling.

{
background: none;
    border: none;
    colour: inherit;
    cursor: pointer;
    font: inherit;
    padding: 0;
    define: inherit;
}

Writing our glossary entries utilizing Markup

We will probably be writing sections of our glossary as description lists, additionally generally known as definition lists. Right here is an instance checklist of glossary objects underneath the letter A, associated to assistive applied sciences:

See the Pen
Description Record Accessibility Phrases Letter A
by Bryan Rasmussen (@bryanrasmussen)
on CodePen.

The phrases and definitions have themselves been borrowed from usability.gov.

Except for that, as you already know, we will probably be utilizing buttons to signify the letters of our glossary, which can look much like this:

<button class="letter" aria-label="Glossary letter A">A</button>

Our first glossary try

Right here, we’ve a easy first try at a glossary. The glossary is hidden, however there’s a button that claims Present Glossary. When clicked, the glossary turns into seen and the button turns into invisible.

See the Pen
glossary step 1
by Bryan Rasmussen (@bryanrasmussen)
on CodePen.

Glossary hidden:

Show Glossary button

Glossary proven:

The open glossary with no clear focus point

However, in fact, we have to use a screenreader with what we’ve — and proper off the bat there are some issues which can be simply no good.

For instance, we are able to see that not each considered one of our letters comprises subitems within the glossary as a result of we’ve disabled the letters that don’t have something underneath them. However how do those self same letters current to a screenreader?

Under, on the left, you’ll be able to see a few of these disabled buttons; on the appropriate is the net rotor Kind Controls menu for the web page.

The disabled buttons on the left and the web rotor form on the right

That’s actually irritating. The disabled buttons nonetheless present up within the Kind Controls, which implies that if somebody goes to hearken to all of the out there buttons, they may also hear these dimmed buttons.

It’s true that they’ll hear that the button is dimmed, understand that the letter doesn’t enable interplay, and presume it’s as a result of it doesn’t have any entries within the glossary. Nevertheless it appears arduous to convey that data that method.

Moreover, there is no such thing as a fast strategy to go to the precise present, opened glossary content material; thus, in case you begin going by way of the glossary along with your screenreader, you’ll have to learn every button first, earlier than you get to the content material.

This additionally applies in case you click on one of many buttons, let’s say button B. You’ll nonetheless need to undergo all of the buttons of the alphabet earlier than you get to the glossary phrases you made seen if you clicked the letter B.

Lastly, most screenreaders show completely different behaviors when interacting with content material within the browser than when the consumer interacts with it straight. Right here, for instance, is what the glossary appears like when VoiceOver is used to click on the Present Glossary button:

Use VoiceOver to open the glossary

That’s proper, the glossary is proven, however the focus continues to be on the now-hidden button.

The identical factor occurs right here if you click on the Shut Glossary button.

The Close Glossary button when focused

Lastly, if you’re not a screenreader consumer however are utilizing the keyboard to navigate between parts, our unstyled buttons don’t adequately present focus settings.

Eradicating unusable options from the screenreader

Right here, I’d counsel we take away the elements of the glossary that aren’t usable from the screenreader.

Let’s repair these points. Right here is our subsequent model:

See the Pen
glossary step 2
by Bryan Rasmussen (@bryanrasmussen)
on CodePen.

First, let’s deal with the straightforward low-hanging stuff: including a pleasant focus type for the Shut button and the letters.

The Shut button, when targeted, will get a navy-colored background and a white-colored X.

The close button with a white X and navy background

The letters get the identical styling in a rounded button, however with some additional padding to provide a pleasant expertise of them coming out.

.letter:focus {
  text-decoration: none;
  border: 2px stable #000;
  border-radius: 300px;
  padding-left: 10px;
  padding-right: 5px;
  padding-top: 2px;
}

.letter:focus ,.shut:focus {
  define: blue;
  background-color: navy;
  colour: white;
}

Focus on current letter in the glossary

Eradicating disabled buttons from the screenreader view

Second, let’s eliminate all of the disabled buttons. That is simple sufficient to do; if they’re disabled, we are able to additionally give them an aria-hidden="true" attribute.

Clearly, each the glossary sections and the headings for these sections ought to solely be out there when that letter has been accessed. In any other case, we’d run into the issue we mentioned earlier than of getting an excessive amount of content material to successfully navigate.

Our most important issues will probably be specializing in the weather and getting our screenreaders to observe our focusing in several browser combos.

We’ve two conditions during which we have to change the main focus:

  1. After we open the glossary, we need to transfer the main focus away from the Present Glossary button into the precise glossary content material
  2. After we click on a glossary letter, we need to transfer the main focus into that letter’s content material

When wanting on the glossary, you’ll be able to see the letter A content material on the appropriate of the glossary. While you go to the subsequent letter B and click on, you’ll see the content material on the appropriate get changed with the content material for the letter B.

However, if you’re utilizing a screenreader and are visually disabled sufficient that you just can not see the content material seem on the appropriate, when you find yourself shopping within the letter A and click on the letter B, you’ll not have entry to the content material.

This is the reason the second level is necessary. In case your focus isn’t set for you onto the content material that turns into seen, you would need to navigate by way of the entire checklist to get into the content material! That may be very annoying.

To permit navigation into the letter content material, put a heading on the high of every part so that you could use heading navigation to get there rapidly. Then, set the main focus contained in the glossary part if you click on on a letter. Within the heading is a button to go to the subsequent letter.

Working with VoiceOver in Safari

Completely different Safari variations can have difficulties when altering the main focus to different parts based mostly on a button occasion that includes VoiceOver. There are some workarounds for this, similar to utilizing an A ingredient appearing as a neighborhood hyperlink with function attribute="button", or, as I’ve performed within the code for this text, working your focus code inside a setTimeout with higher than 0ms. I’ve performed it with a 16ms setTimeout to put it on high of the subsequent iteration of the occasion loop (with, in fact, the standard provisos making use of).

In fact, if this was being performed in a React or comparable mission, we’d render parts based mostly on state adjustments from the press occasions, and in that case, we’d resolve to make use of the autofocus attribute on the weather we need to give attention to, however on this case, we are going to set the main focus dynamically with JavaScript.

So, I believe we’ve one thing performed that’s cheap. To show it, I’m going to indicate some screenshots of how I anticipate a screenreader consumer (on this case utilizing VoiceOver) will navigate the glossary.

First, we enter the web page with VoiceOver. When you press the VoiceOver key mixture (CTRL-option-U), you’ll see the next:

Enter the page using the VoiceOver key combination

This isn’t that fascinating to take a look at, nevertheless it reveals you that you’ve got two methods to get to the glossary button. Urgent the VO key + down key will choose the glossary button:

The glossary when hiddenClick on it and the glossary turns into seen with our focus set on the heading for the letter A contents.

The glossary when shown

As you’ll be able to see, VoiceOver will present the sections it’s at present targeted on because of the VoiceOver cursor being turned on. For improvement functions, I believe it’s actually helpful, and customarily talking, many screenreader customers who should not blind use the cursor to assist maintain visible observe of the place they’re on a web page.

After we open up the glossary and take a look at the Kind Controls once more, we are able to see that solely our non-disabled buttons can be found as a result of we added aria-hidden="true" to each button that can also be disabled.

Only the non-disabled buttons are visible

With this, customers conversant in our glossary on a web page the place it’s discovered can open the glossary, go on to the Kind Controls, and navigate right down to the letter they need with out having to undergo the heading, shut button, textual content sections, and so forth.

You’ll discover we’ve that Go to Subsequent Letter button. Right here, it relies on you holding observe of your context if you wish to use it, so one would possibly need to both not use it in any respect, or so as to add extra content material, like altering the label to be Go to Subsequent Letter (B), assuming the at present energetic button is A.

That is the purpose at which genericity should give strategy to the way you need your website to work, in the identical method generic parts may have types modified to suit a website’s general appear and feel.

When the consumer selects a button from the Kind Controls menu, they may find yourself with that button chosen on the web page.

The open glossary has a visible focus on the letter DAt this level, they’ll click on the button, present the definitions for that letter, and set the give attention to that letter.

The definitions are shown with a clear focus on the letter indicated

We will see that whereas there is no such thing as a seen h2, we’ve targeted on it and the screenreader has learn it to the consumer. In the event that they navigate to the subsequent step, they get:

Our generic Go to Next Letter button

Right here we’re once more, in a matter of opinion. There are a number of points you’ll be able to see within the alternative of a Go to Subsequent Letter button, and these would possibly make leaving it out altogether or altering its location within the DOM price contemplating.

The primary challenge is that we don’t have a visual Go to Subsequent Letter button, which means that individuals who use a screenreader that may see is likely to be confused by this step. In fact, we didn’t have the earlier header, both, however that’s much less problematic as a result of when including in this stuff that one can not see it’s best to have it observe the visible context as intently as potential. It’s not so disorienting to see or hear a couple of header underneath the letter you clicked as it could be to be informed a button is there to click on with out with the ability to see such a button.

As this instance has such quick glossaries, it would make sense to have the Go to Subsequent Letter button on the finish of every part of phrases, otherwise you would possibly resolve to take away it altogether and depend on individuals to make use of their screenreader’s internet rotor to go to the subsequent button, which might work equally effectively in case you had few definitions or many.

It is likely to be complicated for a consumer to have the Go to Subsequent Letter button earlier than the definitions as a result of customers who’re really blind would possibly assume that meant there have been no phrases outlined for that letter.

Lastly, there’s a limitation of the Go to Subsequent Letter button as introduced within the rotor:

The limitations of having a Go to Next Letter button

When utilizing the rotor, you aren’t informed what the subsequent letter could be and even what the present letter is.

Enhancing the navigation

It is likely to be helpful to have the present Glossary letter button say if it had been the at present displayed letter, i.e., the textual content reads Presently Displaying Glossary Letter A button, and the Go to Subsequent Letter button says Go to Subsequent Letter, B button.

Thus, if you’re navigating down the checklist of buttons within the rotor, you might have two locations that can simply place your context.

I’m going to make these adjustments, which might be seen right here:

See the Pen
glossary step 3
by Bryan Rasmussen (@bryanrasmussen)
on CodePen.

For the reason that Go to Subsequent buttons are all within the markup, it will be as much as no matter code you’re utilizing to supply your markup to generate that (whether or not templates, React, Vue or simply doing it by hand). The one related change is within the switchSelectedLetters operate, which is named everytime you click on one of many glossary buttons, as proven under:

const switchSelectedLetters = (goal) => {
  const selector = "selectedLetter";
  const currentSelectedLetter = doc.querySelector(`.${selector}`);
  const currentAria = currentSelectedLetter.getAttribute("aria-label");
  const targetAria = goal.getAttribute("aria-label");
  const selectionText = "Present chosen, ";
  //use [...selectionText] as a result of we wish variety of characters, not code items.
  currentSelectedLetter.setAttribute("aria-label", currentAria.substring([...selectionText].size))
  currentSelectedLetter.classList.take away(selector);
  goal.setAttribute("aria-label", selectionText + targetAria);
  goal.classList.add(selector);
}

Let’s go along with these adjustments and use the glossary once more. You might be knowledgeable that the glossary button you might be at present accessing is the at present chosen button.

Our new Go to Next Letter button

While you click on the Subsequent button, it turns into the at present chosen button, and you’ll see this within the rotor. Moreover, the Go to Subsequent Letter button additionally tells you what that subsequent letter will probably be.

Our final, accessible glossary Form Controls display

I believe that, in the long run, this implementation provides us some good options to make a usable, accessible glossary of definitions that can profit not simply blind customers, but in addition different customers of screenreaders.

Adapting our accessible glossary for mobility-challenged customers

Lastly, I’ll present rapidly how all the pieces is accessible for mobility-challenged customers who would primarily use the keyboard for navigation.

The Present Glossary button is tabbable to, and signifies when it’s targeted:

The Show Glossary button when tabbed to

Clicking the button opens the glossary:

Opening the glossary with the tab keyUrgent Tab once more selects the Shut button:

Close button selected using Tab

The subsequent Tab selects a letter:

Hitting tab again selects the next letter

When you tab, you’ll go to the subsequent letter. After that, you’ll be able to click on to see the letter’s definitions, and in case you tab after that, you can be at Shut Letter once more, so you’ll be able to shut at any time fairly rapidly. You would possibly need to add a handler for the Escape key, on this case, to allow closing the glossary by urgent the Escape key, however because it stands now it’s usable and, I believe, logically comprehensible.

Conclusion

Making one thing accessible will not be particularly tough, so long as you’ll be able to envision the issues your shoppers will encounter and have in mind the constraints and fashions of the world that varied assistive applied sciences need to work from.

: Debug JavaScript errors extra simply by understanding the context

Debugging code is all the time a tedious job. However the extra you perceive your errors the simpler it’s to repair them.

LogRocket lets you perceive these errors in new and distinctive methods. Our frontend monitoring resolution tracks consumer engagement along with your JavaScript frontends to provide the capability to seek out out precisely what the consumer did that led to an error.

LogRocket information console logs, web page load instances, stacktraces, gradual community requests/responses with headers + our bodies, browser metadata, and customized logs. Understanding the influence of your JavaScript code won’t ever be simpler!

.

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments