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:
- Isolate generic focus declarations by using
:focus-visibleinstead of the blanket:focusparameter. - Provide an overt outline with an explicit offset to keep the ring independent of bounding box clipping.
- 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:
- Establish a clear global token definition block specifying thickness, style, color, and offset values.
- Bind token values to central system colors so that dark-mode and light-mode focus properties switch automatically.
- Validate that utility components do not clip focus boundaries via
overflow: hiddenparameters 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
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:
- Use a native HTML
<button>element to act as the interface trigger. - Bind an
aria-expandedattribute to the trigger button, toggling betweenfalseandtrueas the visibility state changes. - Link the trigger button to the target container using an
aria-controls="container-id"pointer. - Keep target container items accessible in the natural tab layout order. Avoid stripping standard tab stop indices from native links.
- Let the user press
SpaceorEnterto toggle visibility. Do not intercept arrow keys; let the user tab naturally into the revealed options. - Provide an option to close the panel if the user presses the
Escapekey, returning focus cleanly to the trigger button. - When using icons inside the trigger button, include an explicit
aria-labelor a hidden text string to announce the button's action clearly. - 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