Showing posts with label accessibility. Show all posts
Showing posts with label accessibility. Show all posts

Tuesday, November 6, 2018

A Journey of One Thousand Miles: Different styles and uses of progress indicators

One feature, common to nearly every process (and especially most processes in ecommerce), is something that indicates progress - a map, if you will, that shows your current location relative to the destination. Even our Instant Pot has a display that indicates when pressure builds and releases. But, just as every process is different, there should be different techniques that indicate the process and the current state.

One of the most common uses of progress indicators is in multi-page forms - that's certainly where I've had the most exposure to them. In general, they're intended to reduce cognitive load in a process, and they can either succeed or fail, often with significant results.

In the Web Accessibility Initiative section for multi-page forms, several different methods for identifying progress are put forward. The methods used to indicate progress for multi-page forms can be briefly described as (a) landmark content, (b) a progressbar, and (c) a step-by-step indicator - and I'll take each of them in turn to discuss how they might be used and whether or not they can, or should, apply to other types of progress.

Landmark Content

The use of landmark content to identify progress is almost always a good method, especially when - as the first approach identified by the WAI - updating the title element is used. As a general rule, assistive technology will announce changes to the page title. The other approach in the landmark content method, updating the main heading - i.e. the h1 element - is also a good approach as many users navigate using headings and it is, or at least should be, more visible than the page title. Rather than use one of these approaches, use both.

Of course, there are disadvantages to using this method. Neither approach - updating the page title or updating the main heading - is likely to be sufficient if the user has scrolled far enough. Updates are likely to be noticed only by users who have the main heading in their field of vision or are using assistive technology that announces changes. Also, both approaches in this method update content, so not all accessibility is improved - the user still must either read, or have assistive technology that will read, the updated content.

A Progressbar

A progressbar generated using a progress element with a value of 1 and a max of 3, as rendered by Chrome
Progressbar
(from a progress element, rendered in Chrome)
HTML5 offers a progress element that takes a max attribute and a value attribute to draw a visual representation. The progress element takes content, which must be updated, as in <progress max="7" value="1">Step 1 of 7</progress>. However, in some platforms, a progress bar is animated in a way that would violate the Web Content Authoring Guidelines Success Criterion 2.2.2, an A-level criterion.

Like several of the additions in HTML5, the progress element is not very accessible, so it's still recommended a better widget - one that uses the progressbar role with aria-valuemin, aria-valuemax, and aria-valuenow - be used, but be advised that automatic updates to the value in a progressbar role are not well-defined.

The progressbar, whether implemented using the HTML5 progress element or a widget that uses the progressbar role, may be sufficient if the progress reflected is proportional, such as a file transfer showing the number of bytes transferred. The interface is not well-suited to processes where one or more steps is larger, or takes more time, than others.

A Step-by-step Indicator

An ordered list as a step-by-step indicator
Step-by-step Indicator
The third method - a step-by-step indicator - can help users orient themselves in multiple ways. First, the user should be able to clearly see how much progress they've made, whether the progress within each segment is proportional or not. Second, the content should reflect not only steps already completed but the current step, and not-started, or upcoming, steps. In this method, there are three common approaches we can use, and each will apply to different cases.

Fixed-Journey Indicator

The basic step-by-step indicator presented for multi-page forms by the WAI is an ordered list, with list items that have visually hidden content to indicate which item is completed or current. This is likely sufficient, if the progress is a consecutive series of unidirectional steps under the control of the user - although the WAI example should be updated to reflect capabilities available in the ARIA states and properties.

Breadcrumbs

If, progress is bidirectional or the user may complete steps in a non-consecutive manner, the interface should be a navigational one which allows the user to choose the step they'd like to complete. This step-by-step indicator becomes more complex as it not only needs to include completed, current, and not-started states but also accessible navigation between the steps. This sort of navigational, step-by-step indicator is often called a breadcrumb because it's more than just a progress indicator.

This type of progress indicator should especially be used for multi-page forms if those forms cause legal commitments or financial transactions to occur or update user-provided data that has been stored to help meet WCAG Success Criterion 3.3.4 as it aids in the review, confirmation, and correction of information.

Status Indicator

The third type of step-by-step indicator is a status indicator. The status indicator is still, semantically, an ordered list, but a status may switch in a non-consecutive manner and the status is likely to be outside the control of the user. An example of this might be a payment transaction that moves from pending to authorizing to completed or a document retrieval that moves from requesting to receiving to received to loaded. In either of these cases, an intermediate step may be skipped, e.g., the payment may appear to move from pending to completed or the document may move from receiving to loaded.

This type of progress indicator is perhaps the most complex, because the user interface is not really a progress indicator but a status indicator (hence the name). The upcoming statuses need not be announced because their inclusion is likely to reduce cognitive accessibility - the user can do nothing to either prevent or encourage the move to that state. Further, announcing which of the items in the list is current lacks the context that the visual interface has, so identifying completed and current items is a little more complex.

It is also important to note that because this indicator is auto-updating and representing something outside the control of the user, it is critical that it only be used for those activities that are essential. If the interface is used for a part of an activity that is non-essential, the auto-update feature without the ability to pause, stop, or hide the update will violate WCAG Success Criterion 2.2.2, just as the HTML5 progress element would.

Conclusion

Any of the four different types of progress indicators - a progressbar, a fixed-journey indicator, breadcrumbs, or a status indicator - can be sufficient to describe process. While they have areas of overlap, each has a specific interface that leads to a design pattern and accessibility features.

In the very near future, I will be launching a gitbook called Think A11y that will be covering components like this, including HTML, CSS, and JavaScript, in an effort to put my accessibility resources in one location. This blog will still cover accessibility issues from time to time, but hopefully this new approach will make my electronic life a little easier to manage and share. In the meantime...

Happy coding.

Saturday, October 27, 2018

Clean Your Tools

Recently, I was reading an interview with Scott Kubie in which he was asked "is there a piece of professional or life advice you've gotten that has always stuck with you" and to which he responded "clean your tools". I was immediately reminded of all the times my father said something similar to me about the care and maintenance of tools.

Often, as a child, I wondered why we spent the time maintaining our tools when they were just going to get dirty or dulled the next time we used them. In the case of some tools, and how they were soiled, I could understand - steel and water result in rust that means a replacement will soon be needed - but unless it means they'll have to be replaced, why clean or sharpen them?

As I worked, I learned that it was difficult - and sometimes impossible - to hold onto a metal wrench covered in oil; I learned that it was difficult - and sometimes impossible - to cut with an unsharpened blade. Well maintained tools, on the other hand, did the job they were designed to do, often wonderfully well. As much as my child self may have hated to admit it, my dad was right. The simple truth is that clean tools work better.

What does this have to do with technology?

More and more the tools we have created to write, test, and manage code are far from clean. They may be have been updated frequently, with bells and whistles added. They've been converted from plain-old semantic HTML, cascading styles, and vanilla JavaScript to the most popular frameworks. But, like a blade that has been sharpened in the wrong direction, our tools have developed a false edge that is likely to break off, leaving our tools dull and useless.

It can't happen - it won't happen, you say? It already has.

If we look at the standard tools developers use - things like BitBucket and WordPress - we find that many of them have significant accessibility issues, often resulting in a failure to meet the WCAG at even A-level conformance, brought on by how they're built and maintained. The latest WordPress editor, called Gutenberg, has consistently had significant accessibility issues and has been called "a regression in terms of accessibility level", frustrating testers to such a degree many refused to even look at it again.

Good engineers notice and point out the ways in which we've failed. For example, in a very public announcement, Rian Rietveld resigned as leader of the WordPress accessibility team, citing several issues that led to her departure - but our industry, as with many others, often tries to shout them down or shut them out, whether they be leads on projects in major organizations like Rietvel or entrepreneurs writing about the "State of Accessibility in Dynamic Web Content".

Although it isn't lost on many familiar with accessibility and the state of our tools that most of the issues cited in the post "I have resigned as the WordPress accessibility team lead. Here is why." (by Rietveld) are associated with React, the poor accessibility in one of the web's most popular tools is an uncomfortable truth that few are willing to even acknowledge.

Although the problem is not isolated to React, the lack of React developers with accessibility experience and the difficulties with accessibility in React itself is a problem for more than just Gutenberg, and for more than just WordPress, which controls nearly one-third of the Internet - it's a problem for any organization that uses React, because it's a problem in the ecosystem.

We've been building with dirty tools, creating an ecosystem that has shifted away from POSH and CSS with unobtrusive JavaScript to one written in a JavaScript tool that has an architecture and uses design patterns designed without accessibility in mind. That practice - that ecosystem - has grown developers who need to be encouraged and inspired rather than simply educated, because they can't, or won't, see why the lack of accessibility is a problem. Some even respond to code that resolves accessibility issues created as a by-product of using this tool with something along the lines of "that's not the React way of writing code", which is only slightly better than the "blind people don't use the web" that I received (as a response to a question about accessibility) when interviewing a candidate for a "senior UI engineer" position.

Granted, this post has, perhaps somewhat unfairly, focused on React when the problem is greater than React. In truth, I could list any number of tools - frameworks, like React, - that are, or have become, a problem. React is a bigger target at the moment because it's so fashionable nearly every organization of any size uses it. Organizations have become convinced that engineers won't work without it - maybe they're right - and engineers insist on using it because without it they find it difficult to land a decent gig.

But...here's something we know - the simple truth is that clean tools work better. It will always be the case that plain-old semantic HTML and lightweight, cascading styles will out-perform and be more accessible than sites written fully in Angular or React. If you're interested in diversity, or if you believe, like Tim Berners-Lee, that "the power of the Web is in its universality" and that "access by everyone regardless of disability is an essential aspect", you should be pushing for clean tools that will get your product in front of the greatest diversity and the greatest number of users.

Happy coding (with clean tools).

Sunday, October 21, 2018

Open Sesame: A better password experience

password inputs with strength indicator from weak to strong
Password inputs are ubiquitous, but they're often poorly designed. Not because they're not announced or lack security features to prevent someone looking over your shoulder and discerning your password. Instead, it's the user experience that's poorly designed.

In order to be as secure as possible, we're encouraged to have strong passwords, but each site's idea of what makes a password strong varies and often users are left to guess what the requirements are until after they've tried to enter a password and it has failed the hidden validation rules. In many cases the only clue users have is a strength indicator that slides from weak to strong.

To improve the user's experience, I'm going to suggest you add a list of the hidden validation rules, something like the following.



  • At least one lowercase letter is required
  • At least one uppercase letter is required
  • At least one number is required
  • At least one special character from the following list is required: !, @, #, $, %, ^, &, or *

Additionally, it is going to be tempting to make these hidden validation rules present only during onboarding, when the user is creating an account. This practice will lead to unnecessary frustration when users try to login but cannot remember their password. The addition of the list of rules to the interface gives additional clues that can trigger a remembered password, so add the validation rules description list any time a user needs to input a password.

Additionally, when using this approach, one might consider hiding these rules behind an accordion or tooltip that is only displayed by some user action; however, I would recommend against that approach as it reduces the accessibility this practice improves.

Another word about accessibility here, and this is best explained through markup. As you will notice in the markup below, which creates the list, uses the aria-describedby attribute to tie the validation rules to the input.


HTML

<label for="password">Password</label> <input aria-describedby="required-features" id="password" type="password" /> <ul id="required-features">   <li class="missing">At least one lowercase letter is required</li>   <li class="missing">At least one uppercase letter is required</li>   <li class="missing">At least one number is required</li>   <li class="missing">At least one special character from the following list is required: !, @, #, $, %, ^, &amp;, or *</li> </ul>

At this point it may be tempting to include an icon - something like <li><i class="missing"></i>At least one lowercase letter is required<li> - however, you should not do this, because it causes a fragmentation issue, which is when the accessible name of an item is generated by the first element rather than appending all elements together. Instead, use the listing as is and use a CSS pseudoelement ::before to generate content, otherwise you're likely to hear "warning sign" repeated for each item in the list and the remainder of the text will not be announced. There are ways around this, of course, but it's generally best to keep to the simplest method.


In the near future, this pattern will be exposed in the roking react repo with automatic updates to the list as the validation tests pass. As with other components in the repo, accessibility issues will be resolved to provide the best possible user interface for everyone. Of course, you're encouraged to develop using this pattern in a way that meets your needs, even without using the roking react repo.

Happy coding.

Sunday, September 9, 2018

The Poor Babel Fish: The importance of clear communication and how to measure it

Meanwhile, the poor Babel fish, by effectively removing all barriers to communication between different races and cultures, has caused more and bloodier wars than anything else in the history of creation. ~ The Hitchhiker's Guide to the Galaxy
With all due respect to Mr. Adams, it wasn't the fault of the Babel fish, or the increased communication between different races and cultures that caused more and bloodier wars. In fact, we know that communicating clearly with each other is generally a good thing - as long as we have good intentions.

One of the few things those of us involved in building human/computer interfaces know for certain is that the cognitive load of the interface matters. The greater the cognitive load, the longer it takes someone to complete a process or read content on the web page. The longer it takes someone to complete a process, the less likely they are to complete the process. Larger e-commerce companies with large datasets, like PayPal and eBay, know how likely a person is to complete the checkout process given how long it takes them.

Cognitive load is also one of the most often overlooked elements of accessibility. We seldom spend time thinking about how difficult, or easy, it is to identify relevant items on a page and whether or not the content hierarchy is perceivable. We also seldom pay attention to how easy, or difficult, content is to read, which is yet another component of cognitive load.

Part of the avoidance of evaluating this last piece - how "readable" content is - is due to the fact that it's generally very difficult to assess "readability". In US English there are two formulas that can be used for evaluation: the Flesch Reading-Ease Score (FRES) and the Flesch-Kincaid Grade Level Formula. These two evaluative tools provide comparable scores for English language in other regions and have been pretty widely used; however, they do not apply to other languages.

The difficulty of assessing languages other than English presents unique challenges to assessing the accessibility of web pages with regard to internationalization. Because of my interest in both internationalization and accessibility, their convergence around another of my loves - language - makes this a very interesting topic for me...and, frankly, the main reason why I'm sharing this with you.

We tend to pay a lot of attention to the Flesch-Kincaid Grade Level Formula in the US, but that's not really a measure of accessibility, because it's not a measure of how easy or difficult it is to read, but a measure against a "typical" student's comprehension...and the whole idea of "typical" should be an anathema within the accessibility community. The Flesch Reading-Ease Score, on the other hand, is not a comparison of the content to other "typical" content, but a measure of the content itself, by analyzing the number of words and sentences and the number of syllables in the words used.

The number of syllables in word, in languages other than English, are not necessarily a measure of complexity, however. As a hypothetical example, if we compare the English (three syllable) phrase "take this drug" with the Spanish (nine syllable) phrase "tomar este medicamento", we get a FRES of 119.19 for English (which maps to roughly third grade, or an 8 year-old) and a FRES of -50.01 for Spanish, well beyond the reading ease of the Harvard Law Review. Even if we used the English phrase "take this medication", the FRES is still 34.59, a whopping 80 points greater than the Spanish phrase...or roughly the difference between fourth grade (US) and college graduate reading levels.

Granted, this is an extremely small, hypothetical example; however, there is simply no way to justify the difference between those two phrases. Even though many standards in the US specify readability requirements using the FRES, there must be a better way to calculate the readability, especially across languages.

If we look outside the US, and about ten years before the Flesch-Kincaid Grade Level Formula was developed, we find the Läsbarhetsindex. This formula is considerably easier to use than either Flesch-Kincaid readability tests - it's the number of words divided by the number of sentences plus the number of "long words" multiplied by one hundred and divided by the number of words. A "long word" in the Läsbarhetsindex is a word with more than 5 letters. The Läsbarhetsindex formula gives a score for "take this medication" of 36 and the score for "tomar este medicamento" is also 36.

While there is a general mapping of Läsbarhetsindex to educational levels in the author's native Sweden, such a mapping does not exist for other countries...which makes sense because every educational system is different. This, however, doesn't affect our use of this measure for accessibility, because as was mentioned before, for accessibility we need to evaluate the content, not necessarily compare the content to an educational level.

Although the definition of a "long word" may vary, depending on the language used, the remainder of the formula should work for measuring the readability of content for accessibility purposes.

To aid in your evaluation work, I've created a library that will soon be published via npm as roking-a11y. In the meantime - before it's published on npm - you can get the source in the roking-a11y repo on my GitHub profile.

I'm also looking into how else this can be used and extended. One of my plans is to perhaps modify the length of a "long word" based on a language code, and perhaps add guidance for specific score ranges. If you have ideas about how else this might be helpful, please leave a comment - I don't track issues or feature requests in GitHub. If you've done research in this area, I'd especially like to hear from you.

Happy coding.

Monday, September 3, 2018

A Country Without a Language: Constructing and using language tags

Tír gan teanga, tír gan anam (a country without a langauge is a country without a soul).
One of the tools everyone who develops web applications or writes web pages uses is Best Current Practice 47 (BCP-47) for what's commonly called a language tag (langtag) or locale code. The BCP 47 practice specification, defined by the Internet Engineering Task Force (IETF), sets out how to specify a language using internationally standard codes.

Since every engineer working with web technology should be using this specification, it would be helpful to have a solid understanding of this somewhat arcane and sometimes confusing specification. What follows is a simplified explanation that leads us to just that.

The Basics

The langtag is constructed by combining a language code from ISO639-1:2002, Codes for the representation of names of languages -- Part 1: Alpha-2 code, called a "language subtag" and optionally, more specific restrictions, also called subtags, for the script used, the region in which the localization is used, and the variant, each separated by a dash. Although there are additional subtags, these four are more than enough to denote a language used. In fact, the common practice within BCP 47 is to compose a langtag that is only verbose enough to uniquely identify the language used, and typically, langtags are composed of only the language and the region subtags. Let's see how this works using a few examples.

A Basic Langtag

Although the most basic langtag is one that consists solely of the language code, e.g., "en" for English, the most basic common langtag pattern is a language separated by regions. Since George Bernard Shaw famously said that "England and America are two countries divided by a common language", we'll use this as an example to construct basic langtags that identify that although the script used is the same, English written and spoken in the US is different than that used in England.

The "common language" is identified by its ISO language code, "en" and each of the regions, the US and England are identified by their respective ISO country codes, US and GB. Combining these two basic subtags results in two langtags, "en-US" and "en-GB", for the US and England, respectively.

Of course we could have added the script subtag to each of these langtags to identify the alphabet used, but since it's the same in GB English as it is in US English, that would not add meaning to the langtag, so it would not be included in this case. In fact, we find that the script subtag is relatively rare, however, to see how it works we'll look at a language that can use different scripts, or alphabet sets - a language such as Irish (or Gaeilge).

A Different Script

Advert in Gaeilge using the latin gaelic alphabet
There is a relatively famous advertisement for Guinness Stout that carries the slogan "Ní féidir an dubh cur ina bhán air", which is written in Irish, or Gaeilge. The Irish language is often written today using a Latin alphabet, much like English, with a liberal use of vowels that include accents like those in the word "Ní"; however, prior to the middle of the 20th century, there was no "h" in the Irish alphabet as the lenition was identified by a dot above a letter. This practice means the same phrase in the original Irish script, LATG, would be "Ní féidir an duḃ cur ina ḃán air", as shown in the advertisement pictured.

This difference would give us two langtags - "ga-latn-IE" and "ga-latg-IE". Since the formal language specification for Gaeilge now uses the LATN alphabet, and we're only verbose enough to identify the language, the "ga-latn-IE" langtag would commonly be shortened to "ga-IE".

A Variant or Two

Now let's turn our attention to the variant subtag.

Variants are seldom used in common practice - there are only 100 registered with the IANA and there are typically few who regularly use any single variant. Variants are often used to denote archaic uses and intermingled languages like the mix of English and Spanish commonly called "Spanglish".

If we turn our attention back to the langtag for the US, we might also want to include a regional variant for the Northeast or Southern US, especially given the differences in third-person word choice (where the common choice for third-person pronouns is "you" and "you" for singular and plural, respectively, in the southern vernacular the singular and plural are "y'all" and "all y'all"). Subregion variants such as this are quite common, even if they do not reach the status of a dialect. Although variants are common, they are not often registered with the IANA, which is a requirement for the variant to be used as a subtag.

One exception to the pattern of unregistered variants is Boontling, a variant of English that is tied to Boonville, California. Since a variant subtag for Boontling - BOONT - is listed in the IANA language subtag registry as a variant of (US) English, its langtag would be "en-boont" or "en-US-boont" or "en-latn-US-boont" if you wished to use the more verbose, which we don't.

It's also possible for a langtag to have multiple variants. The only example I know of for this would be a variant of English spoken in Scotland (typically referred to as Braid or Ullans) that uses the variant subtag SCOTLAND and a variant of this variant that is spoken in Ulster, Northern Ireland, which would make the langtag "en-scotland-ulster" or "en-GB-scotland-ulster".

BCP 47 Implementation

The way in which the specification has been written implementing langtags can be a little confusing. Sometimes variants are widely used enough that they become regional and sometimes variants even become recognized as their own language. One instance of this is the two primary variants of Norwegian, Norwegian Bokmål and ‎Norwegian Nynorsk. Although linguistically these are two variants or dialects, the ISO considers them languages in themselves, which means there are three valid language subtags that can be used to construct langtags for Norwegian in Norway: "no-NO", representing Norwegian in Norway; "nb-NO", representing Norwegian Bokmål in Norway; and "nn-NO", representing Norwegian Nynorsk in Norway.

Difficulties like this aside, however, one of the rules of accessibility (a11y) under the "robust" principle, requires us to include a langtag for documents using the lang attribute. The inclusion of the language allows assistive technology, like screen readers, to announce words and phrases properly and allows user agents to offer dynamic translation.

As anyone who has read authors that sprinkle phrases in multiple languages throughout their work knows, even though a root document has a language specified, there may be portions in other languages. Those portions also need to be spoken correctly and the user may benefit from dynamic translation of them as well. To help with this process, the folks writing the HTML spec made the lang attribute a global attribute, not just an attribute on the document, meaning it can be applied to any HTML element.

So, if you're concerned about the usability of your pages, include the langtag on the document (e.g., <html lang="en-US">) and anywhere else it's appropriate...and even if you're not concerned about general usability, adding the langtag to the document will help you meet the accessibility guidelines (WCAG 2.1, Guideline 3.1, Success Criteria 3.1.1 and 3.1.2) - and we all want that.

Happy coding.

Saturday, August 11, 2018

It's A Trap!

If you read my previous post, you know I'm a big fan of accessibility, and reading this post after the previous may be a little confusing because although one of the Success Criterion (2.1.2) is "No Keyboard Trap", I'm going to tell you how to build one.

The reason I'm going to tell you how to build a 'keyboard trap' is that there is a exception to the 2.1.2 - when a modal window is open. These virtual windows have been called 'lightbox', 'overlay', or even 'dialog' - no matter what name we call them, they restrict control to their own little container...and the "keyboard trap" is only a keyboard trap because the input mechanism the user has chosen is a keyboard. What we're really going to build is a 'focus trap' - something that traps focus to a specific container.

I will preface what I am about to describe by clarifying that the small amount of code here will be vanilla JavaScript, but you can translate the generalized approach here to Angular, ReactJs, or any framework you choose. The idea; however, is not to provide much code, but rather a framework of requirements that will allow you to create the focus trap and to explain the because's associated with the multiple why's that come with how the focus trap is constructed.

First, let's talk about why a 'focus trap' rather than a 'keyboard trap'. If we were building a keyboard trap, we would bind a handler to the keydown event and check whether the key hit was a navigational key, e.g., a Tab or Arrow key. This method works - but only if the method of navigation is via a navigation key and not through a navigation method that does not include keys - like any one of several methods available within an assistive application. As a side note, event listeners for common events - like a keydown, keyup, or keypress - are very expensive, so a focus or blur listener offers performance benefits as well. Additionally, using a focus or blur listener makes more sense conceptually, because what we're really trying to control is focus, not which keys are hit or which things are clicked.

Of course, the immediate problem is that unlike a keydown, keyup, or keypress event, a focus or blur event does not bubble. This lack of bubbling means the event handler that traps focus will have to be listening to every blur or focus event for every focusable element within the container. Here's another point where your performance can be impacted - assigning the listener by putting the function declaration in the listener attachment will drastically reduce performance. Create a focus handler and then add it to each focusable element within the container. Note - a code sample of how to add this event listener to each focusable element is not provided, because each framework provides a different method for traversing a Node tree.

Within your event handler, you're not going to be concerned about where focus is coming from, but where it is going to, because we can already assume focus is coming from somewhere in our container, where we're trying to trap it. Luckily, we have this information in a blur event - it's called the relatedTarget.

Note: The use of relatedTarget inside a blur event is not standard across all browsers. For example, some browsers set relatedTarget for focusOut events but not blur events. Although there is no sure way to make this behavior absolutely consistent, some browsers will set the activeElement prior to firing the blur. It is recommended that you check the document.activeElement if the relatedTarget is null.


One last decision you'll have to make is where to place focus if the user tries to go outside the container. You might consider leaving focus where it is; however, that would trap focus to the last focusable element when the default behavior of moving focus off the last focusable element is going back to the beginning. You just need to decide where the beginning is for your needs. If your modal is a form, you're likely to have a different 'beginning' than if it's a pure dialog.

So our event handler will look something like the code in Example 1...



Example 1 (JavaScript)

const onBlur = (e) => {   /* destructure with a default to handle a null relatedTarget */   const {     relatedTarget = document.activeElement,     } = e;   if (!container.contains(relatedTarget)) {     beginning.focus();   } };


Because this uses the native blur event, it won't just block blurs based on navigation keys, but will block all attempts to blur. There will be a slight performance impact because the handler is bound to all focusable elements within a container, but that cannot be avoided - just be sure to remove the listeners when the modal is not displayed.

So, there you go - that's all there is to it. As long as this is used exclusively in a modal, there aren't additional accessibility issues associated with the trap - it's use within a modal doesn't violate the Keyboard Accessible guideline via Success Criterion 2.1.2 - in fact, it makes your modal more accessible than if it lacked the focus trap.

Happy coding.

Monday, July 23, 2018

One For All and All For One



All for one and one for all, united we stand divided we fall. Alexandre Dumas, The Three Musketeers 
I've been putting off attempting to write what I might call "What I've learned about accessibility in twenty years" for a while - partly because even though it's based on a presentation and therefore already written (in a sense), copying PowerPoint slides as images is not very satisfying. Mostly, though, it's because it's likely to be a really long post and those often tend to not perform well. Considering what I've seen in the industry recently though, it's maybe past the time I should have done it, either way, here it goes.

Before I seriously dive into this topic, I want to share a little information about myself. Over the past (almost) two decades I've worked with accessibility in both the public sector, where I was bound by Section 508 of the Rehabilitation Act (1973), and in the private sector, where I've worked with guidelines that are now published as the Web Content Accessibility Guidelines (or WCAG). Over that time I've not only built a significant amount of what we might call "product knowledge" about accessibility, but have built quite a bit of passion for the work as well. I'm going to attempt to share that passion and attempt to convince you to become what I call an "Acessibility Ally" (A11y*ally, A11y^2, or "Ally Squared") - someone who is actively supportive of a11y, or web accessibility.

What Is This Accessibility Stuff, Anyway?

A lot of discussions about interface accessibility start with impairment. They talk about permanent, temporary, and situational impairment. They talk about visual, auditory, speech, and motor impairment (and sometimes throw in neurological and cognitive impairment as well). They'll give you the numbers...how in the US, across all ages,
  • approximately 8 percent of individuals report significant auditory impairment (about 4 percent are "functionally deaf" and about 4 percent are "hard of hearing", meaning they have difficulty hearing with assistance)
  • approximately 4 percent of individuals report low or no vision (which are not the only visual impairments)
  • approximately 8 percent of men (and nearly no women) report one of several conditions we refer to as "colorblindness"
  • nearly 7 percent of individuals experience a severe motor or dexterity difficulty
  • nearly 17 percent of individuals experience a neurological disorder
  • nearly 20 percent of individuals experience cognitive difficulties
They might even tell you how all those numbers are really First World numbers and when you go into emerging markets where reliable access to resources is more limited the numbers double. They'll talk about how, in general, those numbers are skewed by age and how about 10 percent of people under the age of 65 report impairment while more than 25 percent of people between the ages of 65 and 74 report impairment (and nearly 50 percent of those 75 and older report impairment).

I don't generally like to start there...though I guess I just did. Accessibility is not about the user's impairment - or at least it shouldn't be - it's about the obstacles we - the product managers, content writers, designers, and engineers - place in the path of people trying to live their lives. Talking about impairment in numbers like this also tends to give the impression that impairment is not "normal" when the data clearly shows otherwise. Even accounting for a degree of comorbidity, the numbers indicate that most people experience some sort of impairment in their daily lives.

The other approach that's often taken is diving directly into accessibility and what I call impairment categories and their respective "solution". The major problem here is a risk similar to what engineers typically refer to as "early optimization". The "solutions" for visual and auditory and even motor impairments are relatively easy from an engineering point of view, even though neurological and cognitive difficulties are far more significant in terms of numbers. Rather than focus on which impairment falls into the four categories that define accessibility - Perceivable, Operable, Understandable, and Robust - we have to, as I like to say, see the forest and the trees. While there is benefit in being familiar with the Success Criteria in each of the Guidelines within the WCAG, using that as a focus will miss a large portion of the experience.

One other reason I have chosen this broader understanding of accessibility is that accessibility in interfaces is holistic. Everything in the interface - everything in a web page and every web page in a process - must be accessible in order to meet the definition of accessible. For example, we can't claim a web page that meets visual guidelines but not auditory guidelines "accessible", and if the form on our page is accessible but the navigation is not then the page is not accessible.

Why is Accessibility Important?

When considering accessibility, I often recall an experience in interviewing a candidate for an engineer position and relate that story to those listening. This candidate, when asked about accessibility, responded something along the lines of "do you mean blind people - they can't see web pages anyway". I've also worked with designers and product managers who have complained about the amount of time spent building accessibility interfaces for such a "small" group of users or flat out said accessibility isn't a priority. I've worked with content writers who are convinced their writing is clear enough for their intended audience and anyone confused by it is not in their intended audience - what I call the Abercrombe and Fitch Content Model.

For those who consider accessibility important, there are a few different approaches we might typically take when trying to sway those who tend be less inclined to consider the importance of accessibility. In my experience, the least frequently made argument for the importance of accessibility is one of a moral imperative - making an interface accessible is the "right thing to do". While I agree, I won't argue that point here, simply because it's the least frequently made argument and this is going to be a post that bounds the too-long length as is.

The approach people most frequently take in attempting to convince others accessibility is important is the anti-litigation approach. Making sure their interface is accessible is promoted as a matter of organizational security - a form of self-protection. In this approach, the typical method is a focus on the Success Criteria of the WCAG Recommendation alongside automated testing to verify that they have achieved A or AA level compliance. The "anti-litigation" approach is a pathway to organizational failure.

Make no mistake, the risk of litigation is significant. In the US, litigation in Federal court has increased approximately 400 percent year-over-year between 2015 and 2017, and at the time of this writing appears to be growing at roughly the same rate in 2018. Even more significant, cases have held third parties accountable and have progressed even when remediation was in progress, indicating the court is at least sometimes willing to consider a wider scope than we might typically think of in relation to these cases. To make matters even more precarious, businesses operating internationally face a range of penalties and enforcement patterns. Nearly all countries have some degree of statutory regulation regarding accessibility, even if enforcement and penalties vary. Thankfully, the international landscape is not nearly as varied as it was, as nearly all regulations follow the WCAG or are a derivative of those guidelines.

So, why, when the threat of litigation both domestically and internationally is so significant, do I say focus on the Success Criteria is a pathway to failure? My experience has repeatedly shown that even if all Success Criteria are met, an interface may not be accessible - an issue I'll go into a little further when I talk about building and testing interfaces - and only truly accessible interfaces allow us to succeed.

What happens when your interface is not accessible - aside from the litigation already discussed? First, it's extremely unlikely that you'll know your interface has accessibility issues, because 9 of 10 individuals who experience an accessibility issue don't report it. Your analytics will not identify those failing to convert due to accessibility issues - they'll be mixed in with any others you're tracking. Second, those abandoned transactions will be costly in the extreme. In the UK, those abandoning transactions because of accessibility issues account for roughly £12 billion (GBP) annually - which is roughly 10 percent of the total market. Let me say that again because it deserves to be emphasized - those abandoning because of accessibility issues represent roughly 10 percent of the total market - not 10 percent of your market share - 10 percent of the total market.

Whether your idea of success is moral superiority, ubiquity, or piles of cash, the only sure way to that end is a pathway of accessibility.

How Do We Become an Accessibility Ally?

Hearing "it's the right thing to do" or "this is how we can get into more homes" or, sometimes the £12 billion (GBP) number - one of those often convinces people to become at least a little interested in creating accessible interfaces, even if they're not quite to the point of wanting to become an Accessibility Evangelist. The good news is that even something as simple as making creating accessible interface a priority can make you an Accessibility Ally.

The question then becomes how to we take that first step - how do we create accessible interfaces. The first rule you have to know about creating an accessible interface is that it takes the entire team. Accessibility exists at every level - the complexity of processes (one of the leading causes of abandonment), the content in the interface, the visual design and interactions, and how all of that is put together in code by the engineers - all of it impacts accessibility.

At this point, I should give fair warning that although I'll try to touch on all the layers of an interface, my strengths are in engineering, so the Building and Testing Interfaces section may seem weighted a little heavier, even though it should not be considered more important.

Designing for Accessibility

If we were building a house we wanted to be accessible, we recognize that we would have to start at the beginning, even before blueprints are drawn, making decisions about how many levels it will have, where it will be located, and how people will approach it. Once those high-level decisions are made, we might start drawing blueprints - laying out the rooms and making sure that doorways and passages have sufficient space. We would alter design elements like cabinet and counter height and perhaps flooring surfaces that pose fewer navigation difficulties. To remodel a house to make it accessible, while not impossible, is often very difficult...and the same concepts apply to building interfaces.

Most projects that strive to be fully accessible start with Information Architecture, or IA (you can find out more about IA at https://www.usability.gov/what-and-why/information-architecture.html). This is generally a good place to begin, unless what you're building is an interface for a process - like buying or selling something or signing up for something. In the case of a process interface, you've basically decided you're building a house with multiple levels and you have accessibility issues related to traversing those levels...to continue our simile, you have to decide if you're going to have an elevator or a device that traverses stairs...but your building will still need a foundation. Information Architecture is like the foundation of your building. Can you build a building without a foundation? Sure. A lot of pioneers built log cabins by laying the first course of logs directly on the ground...but - and this is a very big but - those structures did not last. If you decide to go another route than good IA, the work further on will be more difficult, and much of it will have to be reworked, because IA affects a core aspect of the Accessibility Tree - the accessible name - the most critical piece of information assistive technology can have about an element of an interface.

Once your Information Architecture is complete, designing for accessibility is considerably less complex than most people imagine it to be. Sure there are some technical bits that designers have to keep in mind - like luminance contrast and how everything needs a label - but there are loads of good, reliable resources available...probably more so for design than for the engineering side of things. For example, there are several resources available from the Paciello Group and Deque, organizations who work with web accessibility almost exclusively, as well as both public and private organizations who have made accessibility a priority, like Government Digital Service, eBay, PayPal, and even A List Apart.

With the available resources you can succeed as an Accessibility Ally as long as you keep one thought at the fore of your mind - can someone use this interface the way they want rather than the way I want. What if they search a list of all the links on your site - does the text inside the anchor tell them what's on the other side? What if they're experienced users and want to jump past all the stuff you've crammed into the header but they're not using a scrollbar - is there something that tells them how to do that? Keep in mind that as a designer, you're designing the interface for everyone, not just those who can [insert action here] like you can.

Building and Testing Interfaces

When building accessible interfaces, there is a massive amount to learn about the Accessibility Tree and how and when to modify it as well as the different states a component might have. Much has been made of ARIA roles and states, but frankly, ARIA is one of the worst (or perhaps I might say most dangerous) tools an engineer can use.

We're going to briefly pause the technical stuff here for a short story from my childhood (a story I'll tie to ARIA, but not till the end).

When I was a child - about 8 years old - my family and I visited a gift shop while on vacation in Appalachia. In this particular gift shop they sold something that my 8 year old mind thought was the greatest thing a kid could have - a bullwhip. I begged and pleaded, but my parents would not allow me to purchase this wondrous device that smelled of leather, power, and danger. I was very dismayed...until, as we were leaving, I saw a child about my age flicking one and listening to the distinctive crack...until he snapped it behind his back and stood up ramrod straight as a look of intense pain crossed his face.

ARIA roles and states are like that bullwhip. They look really cool. You're pretty sure you would look like a superhero with them coiled on your belt. They smell of power and danger and when other engineers see you use them, you're pretty sure they think you are a superhero. They're very enticing...until they crack across your back.

Luckily, ARIA roles and states are almost unnecessary. Yes, they can take your interface to the next level, but they are not for the inexperienced or those who lack caution. If you're creating interfaces designed for a browser, the best tool you have to build an accessible interface is Semantic HTML. Yes, it's possible to build an interface totally lacking accessibility in native HTML. Yes, it's possible to build an accessible interface in Semantic HTML and then destroy the accessibility with CSS. Yes, it's possible to build an accessible interface with JavaScript or to destroy an accessible interface with JavaScript. None of the languages we use in front-end engineering build accessibility or destroy accessibility on their own - that takes engineers. The languages themselves are strong enough...if you are new to accessibility, start somewhere other than the bullwhip.

The next topic most people jump to from here is how to test an interface to make sure it is accessible. This is another place where things can get tricky, because there are a number of different tools, they all serve a different purpose, and they may not do what they're expected to do. For instance, there are tools that measure things like luminance contrast, whether or not landmarks are present, or if any required elements or attributes are missing - validating according to the Success Criteria in the WCAG. In this realm, I prefer the aXe Chrome plug-in (by Deque). Nearly all these tools are equally good at what they do, but - and here's one of the places where it can go sideways - tools that validate according to the Success Criteria are a bit like spellcheckers - they can tell you if you spelled the word correctly, but they cannot tell you if you've selected the correct word.

Beyond Success Criteria validation, there are other tools available (or soon to be available) to help verify accessibility, the most common of which are screen readers. Of screen readers available, some are free and some are paid - VoiceOver on Mac and JAWS on Windows are the most popular in the US - JAWS is not free, but there is a demo version you can run for about 40 minutes at a time. NVDA (another Windows tool) and ChromeVox are free, but less popular. In addition to screen readers, in version 61 of Firefox the dev tools should include a tool that gives visibility into the Accessibility Tree (version 61 is the planned release, this version is not available at the time of this writing).

One thing to remember with any of these - just because it works one way for you doesn't mean it will work that way for everyone. Accessibility platforms are multiple tools that share an interface. Each tool is built differently - typically according to the senior engineer's interpretation of the specification. While the results are often very similar, they will not always be the same. For example, some platforms that include VoiceOver don't recognize a dynamically modified Accessibility Tree, meaning if you add an element to the DOM it won't be announced, or it may only be announced if certain steps are taken, and the exact same code running in JAWS will announce the content multiple times. Another thing to remember is that there is no way you will ever known all the edge cases - in the case VoiceOver not recognizing dynamically added elements mentioned previously, it took more effort than it should have to demonstrate conclusively to the stakeholders the issue was in a difference in the platform.

Finally, when you're trying to ensure your interface is accessible, you will have to manually test it - there is simply no other way - and it should be tested at least once every development cycle. Granted, not every user story will affect accessibility, but because have that holistic view of accessibility that acknowledges that accessibility exists at every level, we know that most stories will affect accessibility.

As with design, there are resources available, but good resources are more difficult to find because engineers are opinionated and usually feel like they understand specifications, even though what they understand is their interpretation of the specifications. If you want to become an accessibility expert, it can be done, but the process is neither quick nor easy. If you want to become an A11y^2, well that process is quicker and easier and mostly consists of keeping everything said in this section in mind. Understand accessibility holistically. Make "Semantic HTML" and "ARIA is a last resort" your mantras. Check your work with one of the WCAG verification tools (again, I prefer the aXe Chrome plug-in) and at least one screen reader. Check it manually, and check it frequently.

Being an Accessibility Ally

Being an Accessibility Ally is really not complicated. You don't need to be an accessibility expert (though you certainly can be one if you want)...you just need to see accessibility as a priority and the pathway to success. Being an Accessibility Ally means you're actively supportive of accessibility.

To be actively supportive, one needs to understand accessibility in a more holistic way than we've traditionally thought about it and we need to understand that not only does accessibility accumulate, its opposite accumulates as well. In other words, inaccessibility anywhere is a threat to accessibility everywhere.

To be actively supportive, we need to do more than act the part by designing and building things like stair-ramps with ramps too steep to safely navigate with a wheelchair or Norman doors. We need to make building interfaces that are perceivable, operable, understandable, and robust a priority...and we need to make that priority visible to others.

When we're actively supportive and people see our action, only then will we be the ally we all need...and we all need all the allies we can get.



For another take on age and web interfaces, you may want to take a look at "The Danger of an Adult-oriented Internet", a post in this blog from 2013 or A11y Squared, a post from 2017. 

Saturday, June 30, 2018

Why you should never code for new browsers

A quick, very short post today.

First, I should preface this by saying that I've been writing human/computer interfaces for a very long time...and for a good part of that time - it's been more than two decades now, I've been writing for these crazy user-agents we call browsers. The Mosaic Wars are a little fuzzy, but I remember the First Browser War vividly.

Every great once in a while, I see a question along the lines of "is x compatible with some-really-old-browser" and there's always a response along the lines of "no one uses that browser anymore, if you're coding for anything older than n - 1, then you're wasting money".

I can say with 100 percent certainty, that if you're coding for specific browsers - be they old or new - then you're wasting money.

Browsers are released very frequently - for Chrome and Firefox, it's typically about every 6 weeks. The specs they claim to support are release much less frequently...for example, a new HTML spec was release every 1 or 2 years between 1995 and 1999 when HTML 4.01 came out, but the next spec - HTML5 - didn't come out for 14 years. CSS first came out in 1996 and was updated about every 2 years until CSS 3 came out (in 1999). 

What's that I hear? A host of voices singing the popular refrain "but we use JavaScript"? JavaScript is finally to the point where it is currently being updated annually - which makes it the fastest changing language of front-end development and still much slower than 6 to 8 times a year.

Add into this mix of rapidly updating browsers the mix of assistive technology (with its own specifications), and we begin to get a picture of extremely volatile user-agents and very stable specifications.

If there was one thing we should have learned from the First Browser War, it's that we should be not be coding according features that are available in one browser that we then try to port to another browser with extra work. Determine what your needs (and wants) are, code to the specification, and let the browsers catch up. Browsers update much faster and are very likely to render your code as you want it to look within the year without additional work from you. Also, this approach is as backwardly-compatible as possible (what in the accessibility world we call being robust)...and if you're not attempting to deliver a product to every end user, regardless of the user-agent they use, then you really are wasting money.

Happy coding.

Saturday, May 26, 2018

Finding Your Way

One of the common challenges when writing interfaces is describing processes that have multiple steps in a way that is both understandable and accessible. Adding different functionality and different devices further complicates this. If we were Hänsel or Grethel, we would just leave a trail of pebbles or breadcrumbs.

Alas, we often find that even though we are not Hänsel or Grethel, navigation within a process is still often a problem and poorly written HTML or CSS can significantly contribute to the several common accessibility concerns and usability concerns surrounding the progress/breadcrumbs component as well. This post offers a pattern that is accessible and mobile friendly without being a burden.

Again, the HTML and CSS needed to provide a usable breadcrumbs component is relatively simple, but it can pose an even greater problem if it is not written correctly. It should also be noted that in addition to the pattern described here, it is very important that the page title and the primary heading should be modified to indicate the update progress.

When first building our progress bar or breadcrumbs, we must make the determination if our it represents unidirectional progress or if we might be able to restart the process. If the flow is unidirectional, you might consider using the progress element to demonstrate progress; however, be aware that the progress element is dependent on the OS in use, and the ability to modify the display is limited.

If we are providing the ability to move backward in the process - i.e., the process is not unidirectional - that means the breadcrumbs or progress bar has a navigational element, and it should be identified as such. The good news is that much of the code is unchanged. To demonstrate the difference in the code, both versions are provided below.

Image showing breadcrumbs with the current step highlighted, in both mobile and desktop.
Breadcrumbs Snapshot
The code below, is complete, with the exception that in the demonstration there is a style rule to center the content, and it produces the breadcrumbs show in the Breadcrumbs Snapshot.



HTML (without navigation)

<div class="breadcrumbs">   <ol >     <li>       <span data-step="#1" role="text">         <span class="description">Personal Information</span>       </span>     </li>     <li aria-current="step">       <span data-step="#2" role="text">         <span class="description">Financial Information</span>       </span>     </li>     <li>       <span data-step="#3" role="text">         <span class="description">Review Information</span>       </span>     </li>     <li>       <span data-step="#4" role="text">         <span class="description">Thank You</span>       </span>     </li>   </ol> </div>



HTML (with navigation)

<nav aria-label="Breadcrumb" class="breadcrumb">   <ol>     <li>       <a href="signup/1">       <span data-step="#1" role="text">         <span class="description">Personal Information</span>       </span>       </a>     </li>     <li aria-current="step">       <a href="signup/2">       <span data-step="#2" role="text">         <span class="description">Financial Information</span>       </span>       </a>     </li>     <li>       <a href="signup/3">       <span data-step="#3" role="text">         <span class="description">Review Information</span>       </span>       </a>     </li>     <li>       <a href="thankyou">       <span data-step="#4" role="text">         <span class="description">Thank You</span>       </span>       </a>     </li>   </ol> </nav>

A few items to note - one is the inclusion of the aria-current attribute, which lets users of assistive technology know which step is current, and another is the inclusion of the role attribute, which fixes a 'feature' in some assistive technologies that sees child elements as distinct from their wrapping elements, resulting in a different value for the accessible name than what would commonly be expected. Otherwise, the code should be self-explanatory.

Next, we add some CSS



CSS

.breadcrumbs {   display: inline-block;   width: auto; } .breadcrumbs ol {   list-style-type: none;   margin: 0 auto;   overflow: visible;   padding: 0; } .breadcrumbs ol li {   float: left;   background: darkgray;   border: 0.1em solid darkgray;   color: white;   padding: 0.5rem;   position: relative;   margin-right: 1rem; } .breadcrumbs ol li::after {   background: darkgray;   content: '';   display: inline-block;   height: 0.5rem;   left: 100%;   margin: 0;   padding: 0;   position: absolute;   top: 0.7rem;   /* width = margin-right + (border-width * 2) */   width: 1.2em;   z-index: -1; } .breadcrumbs ol li:last-of-type {   margin-right: 0; } .breadcrumbs ol li:last-of-type::after {   display: none; } .breadcrumbs ol li a {   background: inherit;   color: inherit;   text-decoration: none; } .breadcrumbs ol li[aria-current] {   background: green;   border-color: green;   color: white; } .breadcrumbs ol li[aria-current] ~ li {   background: lightgray;   color: black; } @media (max-width: 20rem) {   .breadcrumbs ol li {     border-radius: 100%;   }   .breadcrumbs ol li [data-step]::before {     content: attr(data-step);   }   .breadcrumbs ol li a .description {     clip: rect(0, 0, 0, 0);     clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);   position: absolute;   } }

Here again, we need to comment about the code. First, the .breadcrumbs ol li rule is for past steps. This allows us to use the aria-current attribute as the selector for current steps and siblings of aria-current after the aria-current item - .breadcrumbs ol li[aria-current] ~ li - are those steps not yet completed. Another issue to note is that we are using the float property on list items. We might have used the display property to modify where items display, but in many assistive technologies, modification of the display property modifies the accessibility tree, rendering all our effort to construct an accurate tree moot.


Admittedly, this is a simple example; however, it should suffice to demonstrate how a progress bar or breadcrumbs might be built.

Happy coding.

Thursday, May 17, 2018

Hiding in Plain Sight: How to affect what you can't see in your analytics

What if I told you there is a way to improve your Google rank (placement) and significantly increase conversion and that you would not be able to discover how to do it by looking at your analytics? Would you do it? Would it matter what the delta was or would it matter what work was involved?

Several years ago, I worked on a project at PayPal with the sole purpose of improving conversion during checkout. A few "features" were added, but the majority of the project was running A/B tests for (minor) design and content changes for the existing product, so the amount of actual development work was minimal aside from refactoring existing code.

One might think such a project would yield as much as one hundred basis points, but realistically, since these were "minor" changes it should have yielded about half that...but the thing is, it was twice that amount. The most reasonable explanation we might have for this remarkable difference is that we were affecting users that were not even on our radar.

Years before that project, as a side project I took over the website for a non-profit. Before running any A/B tests or modifying design or content in any way, I refactored the code to use semantic HTML and CSS and their rank went from fifth to first overnight. Nearly all the research up to that point indicated that selection of keywords and inbound and outbound links were the primary source for SEO, but here again, something hidden had a significant impact.

In both of these projects, it was the use of solid, time-tested best practices of web development that yielded these results, in particular, Semantic HTML and CSS, unobtrusive JavaScript, and Progressive Enhancement. It was what is ordinarily hidden from users and even those in decision-making roles in technology that had the greatest impact.

Frankly, it seems like an outlandish claim, and had I not seen them firsthand, I would suspect such claims were the usual puffery in which engineers engage - sort of like boosting performance by switching turbochargers. After all, we're often told that the best tools are the newest tools and that time-to-market is the most important factor. Abundant anecdotal evidence demonstrates that neither of those beliefs are based in reality.

Again, here are the four principles behind these transformations.
  1. All HTML was Semantic HTML.
  2. All CSS was Semantic CSS.
  3. All JavaScript was unobtrusive.
  4. Sites were built using Progressive Enhancement.
I should point out that it's possible to use any of these principles alone, and using any of them will give you some of the benefits. The goal when using these practices were to create pages that are
  • fast,
  • flexible, enabling a user to complete the task in any user agent,
  • easily maintained
The primary goal in these projects was to get a page loaded in less than 4 seconds anywhere in the world. Because network reliability and speed are always unknowns outside the US, and even some places within the US, that benchmark meant the page had to load on an internal network in considerably less time. (It also meant I spent time writing a module that would allow me to simulate network rates and reliability that exist in the real world outside the US to more accurately gauge speed...but that's another story.)

The secondary goal was to build pages that would run in any user agent well enough to allow the user to accomplish the task in the shortest amount of time, in part because we know that the amount of time a process takes is inversely proportional to the likelihood of the user completing that process.

The simple truths that govern this secondary goal are that semantic HTML is easier for user agents other than browsers, like the bot(s) that rank your site, to understand; semantic CSS enables you to write fewer, better-performing rules; and unobtrusive JavaScript and Progressive Enhancement expand your audience into non-traditional user agents with the same codebase.

The Problem with Analytics

Examining the effect of these four principles is difficult, in part because of the way data collection for web analytics changed in the first decade of the 21st century. To simplify it, I'll use a mostly hypothetical example.

Let's say you're tracking user agents and see that seventy-three percent of your traffic is coming from Chrome, twenty-one percent is coming from Safari, and five percent is coming from Firefox - like the stats for this site report. Already, one percent is not reported, and if, as is the case for most analytics, your analytics package is using JavaScript to track that rather than the actual web server logs, there are even more users not tracked at all. It's unlikely that you will ever get insight into these users, which is why it has become so easy to dismiss the effect of certain principles, Progressive Enhancement being principle among them.

Progressive Enhancement

One percent is a small number, is it really enough to justify the amount of work Progressive Enhancement requires? On one hand, one percent likely is a small number - unless you're a company like PayPal, with more than 110 million active users - and on the other hand, that one percent represents a much larger number because it's the one percent we know exists. How many users fall into that not-the-popular-browsers group that typically hovers around "one percent", but aren't even measured because their browser isn't identified?

A government agency in the UK tracked visitors to government websites using actual web server logs to determine what percentage of visitors weren't being tracked by their JS analytics package and it was about two percent. Two percent. On government websites. Within a first-world country. For those government websites, that "one percent" is really three percent.

Retail websites are categorically different than government websites, so attempting to extrapolate user behavior in a government-assisted activity to private activity is a little like comparing apples and oranges. The user population in each group has different needs, desires, and expectations, and as a result, have different behavior. All we need consider is the desires and expectations around privacy between the two different categories to see there is a very clear difference in behavior. We can, however, easily support the case that the percentage of tracked users interacting with a government website is likely higher than those interacting with non-government websites. As a result, there is no way to determine what percentage of your actual traffic is untracked unless you are analyzing server logs rather than relying directly on analytics served by JavaScript. The principle of Progressive Enhancement, however, means even these untracked users are served, regardless of the user agent or its features.

Performance Matters

Since we are unlikely to gain insight into the untracked users, what does the data we collect about the tracked group tell us? The primary message we get from the data is that, performance is the most significant issue in web development - it's typically even more important than content. This is not something we've just learned - we've known it for decades. It's also not something that's unmeasured. Organizations frequently calculate the cost of each page or step in a process by calculating the abandonment rate and the drop off rate based on page load time or time-to-interactive, what Twitter used to call "time to first tweet". In a recent, rather finely-tuned test by etsy.com, we see a high correlation between the addition of a mere 160 kilobytes of page weight and a twelve percent drop off.

Semantic Code

Semantic CSS, writing CSS in a way that actually describes something about the code, and semantic HTML, writing HTML in a way that describes the content it contains, expands the robustness of the code (one of the measures of accessibility), is more maintainable, and reduces the amount of code delivered. Semantic code also performs better - there are fewer class and ID selectors to process and a cleaner, more compact Accessibility Tree is built.

Also, lighter pages load faster, and that's important because one of the lessons we've learned from gathering data about tracked users shows that nearly forty percent of users will abandon your site if it takes your page longer than three seconds to "load". If your HTML suffers from divitis and other non-semantic features, or if your CSS is bloated with non-semantic rules, it will take longer to load and parse, pushing the load time further out.

Even worse is the effect non-semantic HTML has on the Accessibility Tree. If your HTML is not semantic, you will have to add code to "fix" the Accessibility Tree, to make your code accessible. Unfortunately, as you add code the risk of harming accessibility even further raises more than the chance you will resolve issues. Here the problems become even more pronounced, because we run into a sub-group of "untracked" users within the tracked users - users who combine accessibility tools with their user agent.

Generally, we only identify site visitors using accessibility tools when they report an issue. There is no method available to determine if a user has engaged an accessibility tool. Conservative estimates generalize that for every accessibility issue registered, at least ten users have been blocked and are unable to complete their task. All industry experts agree about this premise - use of semantic HTML is the best way to minimize the accessibility risks.

A Hypothetical Example

Let's assume that you've looked at your target market and found that seventy-three percent use Chrome, twenty-one percent use Safari, and five percent use Firefox. Almost all - ninety-nine percent - of your users are using agents that have JavaScript enabled by default and you're not aware of "untracked" users. Based on this fantastic news, you've developed your site using ReactJs or Angular and you've tested it locally and the render time is pretty good - it only takes one or two seconds from the request until it's interactive from your development server.

Here's how that plays out in the real world. Your (average) page is really about eighty kilobytes of HTML, about ninety kilobytes of CSS, and almost two megabytes (or more) of JavaScript. If you've not used React's styled elements, your CSS is entirely separate, but nearly all of your eighty kilobytes of HTML is still embedded in the JavaScript. That JavaScript, which has to be entirely loaded before it can be parsed (to make sure there are no syntax errors) and rendered (or hydrated if you've used React's "server-side rendering") is on a CDN, so there's very little latency in the network, but on a 4G connection, mobile devices have a peak of about one-tenth the speed of your local network connection, which means at 100 percent reliability and speed, it's going to take about ten times as long to download the file(s) on a mobile device.

If we assume that you've really optimized and compressed and tweaked your code in production all the ways it's not optimized, compressed, and tweaked in development and your development network is not really that great, the difference between time to interactive on your development site for the more than two megabytes of code is about half of what it will be in production.

So your development version loads in about two seconds, which is pretty fast, and you're pretty confident. In production, your JavaScript resources load HTML into your page in four seconds (versus the two seconds in development) instead of two, but you decide that's still good. Of course, we know you've still lost forty percent of users. Unfortunately, what we now know is that's forty percent of tracked users.

Your beautifully designed site, which only renders for user agents with JavaScript enabled (rendering a "white screen of death" for at least three percent of visitors) unfortunately hasn't undergone an accessibility or usability review and was not written using semantic code. As a result of this oversight, your site has several color contrast issues, navigation is not identified, and your data collection form is not properly labeled - and some unknown portion of the roughly fifty percent of visitors who have made it to your page unscathed cannot complete the task. Here is where we see the final indignity - our analytics cannot tell us why that percentage does not convert, even if it tells us that they do not convert.

An Alternative Example

As an alternative, if your site were written with semantic code using Progressive Enhancement, the code would be lighter, loading in less than four seconds. Your analytics may not have changed, but by using Progressive Enhancement, no one gets a white screen of death, even those in the untracked category, which simply become a hidden bonus rather than a missed opportunity, because the technology fails gracefully.

The semantic code is, by its nature, accessible, and eliminating accessibility issues and offering an estimated ten-fold benefit that taps into an otherwise untracked market - a market that Barclays estimated in 2017 as worth twelve billion pounds, which is not a small number for any organization.

Conclusion

We know sites written with semantic code and unobtrusive JavaScript using Progressive Enhancement
  • perform faster
  • have greater accessibility
  • have greater stability
  • have greater durability
  • are more maintainable
The question is what are these qualities worth to you - do you continue on as usual or do you try to tap into what is hidden in your analytics. We tend to know a lot of information about what we know - it's what we don't know where the greatest promise rests.

Happy coding.