This specification provides a way for authors to make web apps accessible using scripting, rather than the only option being declarative accessibility features of HTML markup. In the first phase, the author is able to programmatically modify the accessible representation of an existing DOM element. In future phases, the author is able to respond to additional input events from assistive technology, create new virtual accessible objects on the page that don't correspond to an HTML element at all, and explore the computed accessibility tree.

Introduction

Explainer

Please refer to the Accessibility Object Model Explainer for the background and motivation.

If you have questions, comments, or other feedback, please file an issue on GitHub.

Document Scope

The Accessibility Object Model spec is narrowly focused on the goal of creating a scripting API for web accessibility. It's intended to complement existing web accessibility APIs such as [[!WAI-ARIA]], not replace them. In particular, this spec attempts to avoid proposing new roles, states, and properties an of accessible objects except where necessary.

Criteria for Inclusion

This specification is not intended to solve all accessibility problems on the Web. It is currently impossible to make some web features accessible, so the primary goal is to resolve immediate needs quickly for existing, inaccessible web interfaces. The specification editors are purposefully deferring many useful ideas in order to maintain a realistic timeline for highest priority features.

We have defined Inclusion/Exclusion Criteria in order to clarify exactly what will be considered in-scope.

Phase 1: Accessible Properties

Extensions to the Element interface

The author can request an accessible node from any valid [[!DOM]] Element.

          partial interface Element {
            readonly attribute AccessibleNode accessibleNode;
          };
        

The accessibleNode attribute returns the accessible node associated with this DOM element. It always returns a valid object if the browser supports the AOM.

AccessibleNode interface

        interface AccessibleNode {
          attribute DOMString? role;
          attribute DOMString? roleDescription;

          // Accessible label and description.
          attribute DOMString? label;
          attribute AccessibleNodeList? labeledBy;
          attribute AccessibleNodeList? describedBy;

          // Global states and properties.
          attribute DOMString? current;

          // Widget properties.
          attribute DOMString? autocomplete;
          attribute boolean? hidden;
          attribute DOMString? keyShortcuts;
          attribute boolean? modal;
          attribute boolean? multiline;
          attribute boolean? multiselectable;
          attribute DOMString? orientation;
          attribute boolean? readOnly;
          attribute boolean? required;
          attribute boolean? selected;
          attribute DOMString? sort;

          // Widget states.
          attribute DOMString? checked;
          attribute boolean? expanded;
          attribute boolean? disabled;
          attribute DOMString? invalid;
          attribute DOMString? hasPopUp;
          attribute DOMString? pressed;

          // Control values.
          attribute DOMString? valueText;
          attribute DOMString? placeholder;
          attribute double? valueNow;
          attribute double? valueMin;
          attribute double? valueMax;

          // Live regions.
          attribute boolean? atomic;
          attribute boolean? busy;
          attribute DOMString? live;
          attribute DOMString? relevant;

          // Other relationships.
          attribute AccessibleNode? activeDescendant;
          attribute AccessibleNodeList? controls;
          attribute AccessibleNode? details;
          attribute AccessibleNode? errorMessage;
          attribute AccessibleNodeList? flowTo;
          attribute AccessibleNodeList? owns;

          // Collections.
          attribute long? colCount;
          attribute unsigned long? colIndex;
          attribute unsigned long? colSpan;
          attribute unsigned long? posInSet;
          attribute long? rowCount;
          attribute unsigned long? rowIndex;
          attribute unsigned long? rowSpan;
          attribute long? setSize;
          attribute unsigned long? level;
        };
        

Initially all AccessibleNode properties must return null.

All AccessibleNode properties, on setting, store the provided value. On getting, they return the user-provided value if present and valid, and null otherwise. The validity of a property valid is specified in greater detail below.

Values set on a DOM element's AccessibleNode are used for the browser's implementation of native accessibility APIs for that accessibility property. When both an AccessibleNode property and its equivalent ARIA attribute are both present, the ARIA attribute overrides the AccessibleNode property.

If a property of AccessibleNode is set to an invalid value, it is ignored.

AccessibleNodeList interface

An AccessibleNodeList represents an ordered list of AccessibleNodes. It's used to represent relationships between one AccessibleNode and other AccessibleNodes in the accessibility tree. Unlike AccessibleNode, AccessibleNodeList has a constructor.

        [
          Constructor(optional sequence<AccessibleNode> nodes = [])
        ]
        interface AccessibleNodeList {
          attribute unsigned long length;
          getter AccessibleNode? item(unsigned long index);
          setter void (unsigned long index, AccessibleNode node);
          void add(AccessibleNode node, optional AccessibleNode? before = null);
          void remove(long index);
        };
        

Mapping to ARIA attributes

In Phase 1, there's a 1:1 correspondence between the set of properties on AccessibleNode and the list of valid ARIA attributes from the [[!WAI-ARIA]] 1.1 spec. This table shows the mappings and also includes deprecated ARIA attributes that are not mapped into AccessibleNode properties.

The Accessibility Object Model does not define new semantics. The semantic meaning of each AccessibleNode property is identical to the meaning of the ARIA attribute.

Accessibility property table
Attribute name Type Equivalent ARIA attribute
activeDescendant AccessibleNode? aria-activedescendant
atomic boolean? aria-atomic
autocomplete DOMString? aria-autocomplete
busy boolean? aria-busy
checked DOMString? aria-checked
colCount long? aria-colcount
colIndex unsigned long? aria-colindex
colSpan unsigned long? aria-colSpan
controls AccessibleNodeList? aria-controls
current DOMString? aria-current
describedBy AccessibleNodeList? aria-describedby
details AccessibleNode? aria-details
disabled boolean? aria-disabled
aria-dropeffect (deprecated)
errorMessage AccessibleNode? aria-errormessage
expanded boolean? aria-expanded
flowTo AccessibleNodeList? aria-flowto
aria-grabbed (deprecated)
hasPopUp DOMString? aria-haspopup
hidden boolean? aria-hidden
invalid DOMString? aria-invalid
keyShortcuts DOMString? aria-keyshortcuts
label DOMString? aria-label
labeledBy AccessibleNodeList? aria-labeledby,
aria-labelledby
level unsigned long? aria-level
live DOMString? aria-live
modal boolean? aria-modal
multiline boolean? aria-multiline
multiselectable boolean? aria-multiselectable
orientation DOMString? aria-orientation
owns AccessibleNodeList? aria-owns
placeholder DOMString? aria-placeholder
posInSet unsigned long? aria-posinset
pressed DOMString? aria-pressed
readOnly boolean? aria-readonly
relevant DOMString? aria-relevant
required boolean? aria-required
roleDescription DOMString? aria-roledescription
rowCount long? aria-rowcount
rowIndex unsigned long? aria-rowindex
rowSpan unsigned long? aria-rowspan
selected boolean? aria-selected
setSize long? aria-setsize
sort DOMString? aria-sort
valueMax double? aria-valuemax
valueMin double? aria-valuemin
valueNow double? aria-valuenow
valueText DOMString? aria-valuetext

Types

While ARIA attributes are all strings, AccessibleNode properties can have many different types. Most of these are straightforward, for example valueNow, valueMin, and valueMax are of type double, while rowCount is of type long.

The primary difference is with ARIA attributes that take one or more IDREFs. In AccessibleNode, they take references to one or more AccessibleNodes directly. This makes it possible to establish relationships between nodes that aren't in the same tree scope, such as in different frames (with the same origin), or in the shadow DOM of a custom element.

In particular, activeDescendant, details, and errorMessage are set with another AccessibleNode, while controls, flowTo, labeledBy, describedBy, and owns all take an AccessibleNodeList.

Validation

Upon setting a property of AccessibleNode, no validation is done. The user-provided value is simply stored, converted to the appropriate type via the standard rules for JavaScript types. This is to ensure that backwards compatibility is maintained; when a new property is added or a new value is recognized as valid, authors do not have to worry that browsers who have not yet added support will break or throw an exception upon encountering this code.

Phase 2: Accessible Actions

See Phase 2

Phase 3: Virtual Accessibility Nodes

See Phase 3

Phase 4: Computed Accessibility Tree

See Phase 4

Acknowledgements

Many thanks for valuable feedback, advice, and tools from: Alex Russell, Bogdan Brinza, Chris Fleizach, Cynthia Shelley, David Bolter, Domenic Denicola, Ian Hickson, Joanmarie Diggs, Marcos Caceres, Nan Wang, Robin Berjon, and Tess O'Connor.

Bogdan Brinza and Cynthia Shelley of Microsoft contributed to the first draft of this spec but are no longer actively participating.