App-like web experiences

Guidance on how to ensure contemporary web experiences are accessible.

Overview

With the rise of Single Page Application (SPA) architecture, there is the growing perception that the web should behave in a more “app-like” manner.

There is no one central definition of what makes a web experience more app-like. Some of these experiences are referred to as web apps, while others are still called websites.

Common hallmarks of an app-like web experience can be, but are not limited to:

  • Near-instantaneous transitions when links or buttons are activated,
  • A more simplified-looking design,
  • Managing application state,
  • Synchronizing data state with a server,
  • Animations and transitions for UI feedback,
  • Persisting state and storage across sessions and devices,
  • Working offline,
  • Utilizing push notifications, cameras, gyroscopes, and other device features,
  • Being able to be installed on a device as a Progressive Web App,
  • etc.

An app-like experience, sometimes referred to as a “web app”, is usually industry shorthand for a modern web development environment that uses contemporary front-end technologies and popular UI trends. Traditional web experiences (websites) can also have these qualities.

Following is advice and guidance for ensuring an app-like experience is still accessible. All concerns raised map to one or more A or AA-level Web Content Accessibility Guidelines success criteria.

Accessibility considerations for app-like experiences

Web apps are built using web technologies. Although their appearance may signal different behavioral expectations for the person using them, they still maintain all the accessibility requirements traditional websites do.

There are also some SPA-specific accessibility considerations to be mindful of when creating an app-like experience:

Valid HTML and the virtual DOM

Virtual DOMs act as the intermediary between some web apps and the browser. They also ultimately need to render HTML markup to the browser, to provide a structure for the web app’s content.

Assistive technology relies on this rendered HTML, in order to communicate:

  • What is on the current page or view,
  • How it works, and
  • What its relationship is to the rest of the content.

Because of this, the HTML authored to construct the web app ultimately must be both valid and semantic, regardless of if it is controlled by a virtual DOM or not.

HTML can be validated via tools such as the Nu Html Checker and Axe DevTools.

Proper use of semantic markup (i.e. using the button element for buttons) must be determined by the developer as part of translating a design into code. GitHub's Annotation Toolkit can help with this.

Client-side routing and focus management

Unlike traditional link-based navigation, which fetches and displays a resource linked to via a href attribute, SPAs use client-side routing.

Routing intercepts URL changes via JavaScript to transition the UI without fetching a new HTML document—it manages browser history and updates the UI based on application state.

Routing is one of the key features of an app-like experience. It allows for near-instantaneous updates to all or a portion of the UI, as well as optionally animating this transition. This mirrors the experience of using many native apps.

Unfortunately, the approach used to create this app-like experience can negatively impact screen readers, whose way of interacting with the web predates SPA-based experiences.

Without a traditional navigation event, the browser does not refresh the tab that the event occurred on. This means the updated experience is not announced to assistive technology, which in turn is not announced to the user. If someone has low or no vision, they may not know the interface has been updated.

Accessible routing

To create an accessible routing experience, the following considerations must be met:

Dynamically set focus

Focus should be set following a soft navigation (staff link) routing update. This can be accomplished via an application of tabindex="-1" on the HTML element you wish to set focus on.

Where focus should be placed is contextual, based on the design and user flow. Following is the general order of preference:

  1. Set focus on the closest most applicable heading element. This heading should provide a short, concise description related to the user’s navigation request.
  2. Set focus on an interactive element. There may be circumstances where focus should be placed on an interactive control such as a button or link. This is highly dependent on the user flow and components used to create this navigation experience. If you are taking this approach, please consult with Accessibility Design (staff only) to determine if this experience is viable.

Broadly-speaking, placing focus on a heading element following a soft navigation event is one of the few times placing focus on a non-interactive element is permissible.

Routing libraries can assist with this experience, but should be manually evaluated to confirm they work as intended. This includes testing on more than just VoiceOver, which is not the most popular screen reader used.

Hard navigation events are synonymous with normal page navigation. They do not need to have focus managed.

Use visually apparent focus styles

Keyboard-only, voice control, and low vision users rely on focus styles to help orient where they are on the screen, as well as understand what action they will undertake. This is especially important in circumstances where screen magnification is being used.

A focus style must be visually obvious and have sufficient color contrast compared to the control it is placed on. Primer components already have WCAG-conformant focus styles baked into them.

Page title updates

The page or view's <title> is an important aspect of communicating successful navigation to people who use screen readers. Unfortunately, soft navigation events do not update the <title> by default.

Ensure a mechanism is present for updating the page or view’s title so that it is reflective of the new content requested by the user. The title should concisely describe the overall purpose of the view (ex: “Pull requests · primer/primitives”).

Text and UI resizing

Many native apps do not provide text or UI resizing controls. Because of this, there is the perception that app content does not resize. This differs from browsers, which allow a user to resize both the type and the UI size.

Apps instead rely on operating system preferences to control this, provided their content is built in such a way that it can honor the user preference request. Regardless of website, web app, or native app format, a UI must support displaying content at a magnified size. This includes preserving all functionality, as well preventing content from being obscured via overlapping or extending past the viewport.

The HTML declaration of <meta name="viewport" content="user-scalable=no" /> was originally used to prevent user resizing. However, nearly all contemporary browsers now suppress this declaration because of the negative impact it has on accessibility and usability.

Animation

Many native apps use both full-screen transitions and smaller inline animations for things like validation and component state.

Larger animations like full-screen transitions have been known to be a trigger for conditions such as vertigo, migraines, and other vestibular conditions. Smaller animations can adversely affect someone’s attention and cognition, especially if the animation pulses and loops.

Flashing and strobing animations are known triggers for conditions such as epilepsy.

Users who are negatively affected by animation may not know they are, so it is desirable to make animation an opt-in experience. Additionally, controls for suppressing animation on an Operating System level may not be known to the user of the OS.

Because of these two factors, it is good to provide a UI control that allows a user to explicitly express their animation preference. This allows someone to deliberately consent to an animated experience.

If an opt-in animation approach is not viable, the prefers reduced motion media feature should be honored by default.

Footers

A dedicated footer provides numerous benefits. It:

  • Consistently demarcates the end of a page or view’s content,
  • Re-lists the primary navigation,
  • Provides mechanisms for becoming aware of, and exploring secondary and tertiary navigation actions,
  • Lists contact and help instructions,
  • Displays copyright and other legal notices,
  • etc.

Like primary navigation, a footer helps users understand the overall structure and reinforces the hierarchy of the experience.

For users where physical actions are laborious, painful, and time-consuming, a footer provides an easy way to navigate to other portions of the experience without having to take multiple taxing actions to navigate back through the main content area.

For users with cognitive considerations, having a dedicated, predictable area that signals the end of main content is highly beneficial for wayfinding and self-help concerns.

Additionally, a footer that is inconsistently displayed across an entire site may lead a user to thinking a portion of the page or view is missing or failed to load.

Swiping and touch gestures

Many native apps support gestures to allow users to accomplish tasks. Some web apps also adopt this behavior.

Any swipe or touch gesture needs an alternate way to accomplish the action performed by the gesture, and this alternate way must support keyboard interaction to facilitate the entire experience. This allows users who cannot perform these gestures the ability to accomplish tasks.

An example of this would be providing a delete button in addition to a swipe right to delete feature, so users with limb loss or upper body paralysis can still delete content.

Orientation

Many apps—including ones provided by the operating system manufacturer—do not adapt their design to the device being rotated into a horizontal or vertical position.

However, this capability is required for all web content, including web apps. To address this, ensure that the entire experience can be used when a device that supports screen rotation is placed into a horizontal orientation.

This requirement is especially important for individuals with motor control conditions who mount devices in a fixed position for daily use. Here adjusting the device may be painful, time-consuming, or not physically possible.

role="application"

ARIA provides the application role as part of its standard. This role communicates that the DOM node—as well as all its children—should behave like a traditional desktop application.

Note that there are no automatic experiential updates that happen to child DOM nodes as a result of this declaration being present. On the contrary, all child nodes will have their native semantics stripped. This means that each and every element will need to have its name, role, value, description, and all expected behaviors manually recreated by the author.

While role="application" may initially seem like a declaration that makes sense when trying to create a more app-like experience, the declaration works counter to an assistive technology user’s expectations.

role="application" forces a screen reader to toggle focus mode on, meaning it passes all key handling directly to the browser. This means that all expected screen reader functionality (such as pressing h to jump to the next heading) is removed. Authors will need to manually re-create this behavior.

Manually recreating all properties and behaviors for each element and screen reader functionality takes a large amount of time, effort, and resources to set up, test, and maintain. Authors must also ensure that the manually-recreated experience works as expected with actual assistive technology users.

For both scenarios, the risk of bugs, regressions, and access barriers being introduced is significant. This is to say nothing of ensuring future allocation of resources to maintain these experiences.

Further reading

Routing

Focus

Resizing

Animation