Massachusetts State Seal

An official website of the Commonwealth of Massachusetts Here's how you know

Official websites use .mass.gov

A .mass.gov website belongs to an official government organization in Massachusetts.

Secure websites use HTTPS

A lock icon or https:// means you've safely connected to the official website. Share sensitive information only on official, secure websites.

Fundamentals: Accessible UX and design

Whether you are a designer mapping out user journeys or an engineer building out a design system, this training is all about making accessibility a natural part of your creative process, not a frustrating checklist that you have to remember to complete.

We'll break down the foundational principles of inclusive design. You'll learn how real people actually experience your interfaces using assitive technologies, how to structure your layouts so they make sense to everybody, and how to pick the right interactive patterns before any code gets written.

You can view this in single page view, that provides all content at once for reference, or you can view this page in guided view, which breaks the content down into sections so you can focus on one part at a time.

Accessible UX & Design

Accessibility is frequently treated as a checklist applied at the end of a software development lifecycle. This approach inevitably introduces design debt, retrofitting costs, and a fragmented user experience. True inclusive design assumes variance in human ability from the outset, providing a resilient foundational architecture that adapts seemlessly across assistive technologies.

The POUR Framework and Human Ability

To pass WCAG 2.2 Level AA conformance, an ecosystem must align with four structural pillars: Perceivable, Operable, Understandable, and Robust. Designing for accessibility requires understanding how diverse human experiences map across these principles through permanent, temporary, and situational spectrums.

A permanent physical impairment, a temporary injury like a broken dominant wrist, or a situational limitation such as glare from direct sunlight all rely on identical underlying programmatic rules. When design system components are engineered correctly, they adapt dynamically to alternative inputs, screen magnifiers, and screen readers without requiring independent, fractured codebases.

Considerations before you start

Before implementing automated components or hardcoding custom elements, design system architects and engineers must evaluate systemic structural strategies. Review the following architectural parameters prior to production.

Can this be solved with native semantic elements?

The most effective, performant, and reliable way to ensure accessibility is to utilize native HTML elements. Native tags like <button>, <a>, <select>, and <details> come equipped with built-in keyboard interaction models, focus mapping, and screen reader announcements out of the box.

Opting to build a custom button using a <div> requires manually rewriting focus catchers, click tracking, keyboard space/enter key listeners, and custom ARIA states. Before writing custom JavaScript to mimic an interface element, confirm that a native semantic HTML element cannot fulfill the design requirement.

Does an accessible design system exist?

Using a confirmed design system that is accessible (like the Massachussetts Design System) can mitigate accessibility issues that may have come up down the road by doing all of that work upfront for you. Using components that have been designed and vetted for accessibility can reduce your workload by a huge margin.

Managing component states

Comprehensive design systems require strict versioning and thorough state matrices. This prevents component breakage across varying screen resolutions and input devices.

When engineering visual libraries, every focusable element must be mapped across its entire lifecycled state taxonomy: default, hover, focus, active/pressed, and disabled. Ensure state styles are declared modularly so that unexpected structural style cascades do not wipe out critical visibility metrics like the focus ring indicator.

Configuring the focus visible architecture

Eliminating native browser focus styles without implementing a highly visible alternative introduces a critical blocker for keyboard users. Configure global stylesheets to treat focus indicators as high-priority layout anchors.

Implementing the :focus-visible pseudo-class

To eliminate the visual noise of focus rings for mouse clicks while keeping them completely sharp and clear for keyboard users, implement the modern CSS pseudo-class.

To integrate this clean focus strategy:

  1. Isolate generic focus declarations by using :focus-visible instead of the blanket :focus parameter.
  2. Provide an overt outline with an explicit offset to keep the ring independent of bounding box clipping.
  3. Ensure the outline color maintains a minimum 3:1 relative contrast ratio against all variant background states.

Building reusable focus tokens

Integrate focus appearance variables directly into your design token system architecture.

To add accessible focus tokens to your core styling sheet:

  1. Establish a clear global token definition block specifying thickness, style, color, and offset values.
  2. Bind token values to central system colors so that dark-mode and light-mode focus properties switch automatically.
  3. Validate that utility components do not clip focus boundaries via overflow: hidden parameters on parent blocks.

Triaging components for keyboard navigation

Before launching a newly engineered component, triage its layout and behavior against keyboard navigation baselines:

  • Tab Sequence Order
  • Internal Widget Navigation (Arrow Keys)
  • Focus Trapping and Bounds Containment
  • Focus Restoration Points

A quick way to test a component's interactive structure is to put down the mouse and rely entirely on the Tab, Shift + Tab, Space, Enter, and Escape keys. If focus lands on hidden items behind panels, disappears entirely from view, or gets trapped inside an element with no way to exit, the structure fails SC 2.1.1 (Keyboard) and SC 2.1.2 (No Keyboard Trap).

If you are building simple navigation clusters, keep focus management lightweight. Elements should live natively inside the regular page flow, allowing users to move seamlessly from link to link using standard tabs. Never inject complex arrow key tracking onto simple lists of standalone links, as this breaks normal browser parsing models.

If you are building complex composite widgets, plan for programmatic focus shifting. Use a roving tabindex approach or aria-activedescendant configurations. When focus enters a composite group like a tab list or grid canvas, the initial container should capture the tab stop. Internal item exploration must then switch exclusively to arrow keys.

If an interactive component dynamically spawns an overlay dialog view, you must programmatically construct a focus trap utility. This ensures keyboard users aren't left tabbing endlessly through background items that are visually hidden behind the modal backdrop.

What cannot be solved by ARIA attributes alone

ARIA attributes do not change a component's behavior; they only change its announcement profile. Before relying entirely on ARIA declarations, audit your designs for core visual problems that attributes cannot patch:

  • Failing color contrast ratios
  • Relying exclusively on color changes to show errors
  • Text embedded inside rasterized images
  • Fixed, rigid layout containers that clip text when reflow scales up
  • Unintuitive visual reading paths that conflict with underlying source code

If a design contains a chart using color alone to differentiate data sets, appending screen reader text is only a partial solution. Sighted colorblind users will still face significant barriers. The design system must provide visual patterns like textures, shapes, or clear data labels directly in the visual asset layout.

Typography scaling and text reflow

For text layouts to be truly accessible, typography must respond dynamically to user text-scaling overrides. Defining typographic hierarchies or layout heights using hardcoded pixel dimensions values stops content from expanding cleanly.

When layouts scale up to 400%, static pixel bounds lead to clipped lines or text spilling over bounding areas. Use relative layout units like rem for type and flexible sizing tokens for layout blocks. This allows components to scale naturally alongside the user's custom browser preferences.

Choosing the correct interaction workflow

At this stage, you should know exactly what type of component behavior your user interface layout demands.

If your component alters view data, updates filters, adjusts preferences, or opens action dialogs, use the Action Menu / Widget Pattern. Apply appropriate roles like role="menu" or role="dialog", set up arrow key focus handlers, track open/closed states using explicit attributes, and manage programmatic focus shifting behind the scenes.

If your component presents a simple, organized list of navigation links, use the Disclosure Pattern. Keep the markup lean by using native link anchors wrapped inside standard list elements and descriptive wrappers like <nav>. Let standard tab keys control focus movement naturally, omitting complex keyboard event overrides.

The layout example below shows a basic structural pattern. It provides a blueprint for separating disclosure states from complex application-style menus.

System Architecture Blueprint

Download Component Specification Blueprint (DOCX)

Use this reference blueprint to guide your design token values, keyboard event listeners, and role properties across various UI components. It tracks when to manage focus manually and when to leverage default browser behaviors.

The Disclosure Pattern Specification

Important! Important architectural rule

Apply the Disclosure Pattern only if the expanded interface panel contains independent navigation items, links, or static informational content. If you use role="menu" on navigation link elements, you create a semantic promise that requires full arrow-key handling and disrupts standard screen reader link reading modes.

The Disclosure pattern uses a simple button to show or hide an adjacent layout container. It is robust, easy to build, and matches native browser behaviors.

To implement the standard Disclosure pattern specification:

  1. Use a native HTML <button> element to act as the interface trigger.
  2. Bind an aria-expanded attribute to the trigger button, toggling between false and true as the visibility state changes.
  3. Link the trigger button to the target container using an aria-controls="container-id" pointer.
  4. Keep target container items accessible in the natural tab layout order. Avoid stripping standard tab stop indices from native links.
  5. Let the user press Space or Enter to toggle visibility. Do not intercept arrow keys; let the user tab naturally into the revealed options.
  6. Provide an option to close the panel if the user presses the Escape key, returning focus cleanly to the trigger button.
  7. When using icons inside the trigger button, include an explicit aria-label or a hidden text string to announce the button's action clearly.
  8. Verify that the expanded layout container remains responsive, adapting to text scaling without breaking layout columns.

This concludes Part 1 of the Accessible UX & Design System Training. Part 2 of this guide covers the following advanced implementation mechanics:

  • Automated & Manual Accessibility Testing
  • Combobox and Auto-complete Architecture
  • Accessible Forms and Live Validation Regions
  • Data Visualization and Complex Table Structuring
  • The Accessibility Object Model (AOM)
  • Dark Mode, Contrast Themes, and High Contrast Overrides
  • Motion Reduction Guidelines

Continue learning

Advanced ApplicationAccessible UX and Design Systems - Part 2