Skip to content

ARIA IDL Updates Mini‐Explainer (ARIA PR #2484)

Rahim Abdi edited this page Sep 21, 2025 · 50 revisions

This is a mini-explainer for: ARIA PR #2484.

Purpose of WebIDL

Web Interface Definition Language (IDL), its purpose and ARIA's Web IDL is thoroughly documented here: https://github.com/w3c/aria/blob/main/documentation/aria-idl.md.

Essentially, WebIDL (IDL for short) defines the interfaces and APIs implemented in browsers including attributes. Attributes have two aspects that represent the same thing:

  • The content attribute which is found in HTML markup, e.g., <button aria-current>
  • The IDL attribute which is manipulated via JavaScript and offers type coercion/validation, e.g., buttonElement.ariaCurrent

To keep both facets of an attribute in sync, IDL attributes can mirror their content attribute which is called reflection:

Reflection is primarily about improving web developer ergonomics by giving them typed access to content attributes through reflected IDL attributes. The ultimate source of truth, which the web platform builds upon, is the content attributes themselves.

Content attributes are simply strings set in the HTML markup, or using the setAttribute() DOM API; on the other hand, IDL attributes use JavaScript dot notation because they are properties of JavaScript DOM objects. Also, the value of a content attribute can differ from its IDL attribute, e.g.,:

// example HTML file

<input id="my-input" type="foo">
...
<script>
let input = document.getElementById("my-input");

console.log(input.getAttribute("type"))  // "foo", content attribute value
console.log(input.type)                  // "text", IDL attribute value (and invalid value default)
</script>

This example demonstrates one of the primary advantages of IDL attributes, which is attribute validation. For the type attribute, when its value is invalid, the browser falls back to a value of text (i.e., invalid value default); the value text is also used when the type attribute is missing (i.e., missing value default).

Motivation for Improving ARIA IDL

Each ARIA IDL attribute currently reflects as one of the following three types:

  • Nullable FrozenArray<Element>? - E.g., ariaActiveDescendantElement
  • Nullable Element? - E.g., ariaLabelledByElements, ariaDescribedByElements
  • Nullable DOMString? - E.g., ariaCurrent, ariaChecked, ariaHidden, ariaLabel, ariaPressed, ariaSort

ARIA IDL attributes that reflect as FrozenArray<Element>? and Element? behave without issue in IDL.

However, taking a closer look at the vast majority of ARIA IDL attributes that currently reflect as DOMString?: this means that the IDL attribute reflects either a null value (a content attribute's absence), or the string value of the corresponding content attribute. This is OK for attributes such as aria-label where the IDL attribute simply string-reflects (e.g., <button aria-label="my accessible button">).

However, like <input>'s type attribute, a large set of ARIA content attributes have a predefined set of values that correspond to unique states. For example, aria-checked supports true, false, mixed. These types of ARIA attributes also currently string-reflect in browsers, e.g.,:

// example HTML file

<button id="my-button" aria-pressed="blah">
...
<script>
let button = document.getElementById("my-button");

console.log(button.getAttribute("aria-pressed"))  // "blah", content attribute value
console.log(button.ariaPressed)                   // "blah", IDL attribute value
</script>

Contrast the developer experience for the type attribute (for <input> elements) with the ariaPressed attribute. Notably, browsers aren't currently doing any validation of ARIA IDL DOMString? attributes, unlike the HTML type attribute. This is because many ARIA content attributes that reflect as DOMString?, and that should behave like the type attribute, aren't defined as enumerated attributes per HTML spec with predefined, JavaScript-enforced keywords, states and missing/invalid value defaults.

To improve ARIA's WebIDL, ARIA PR #2484 converts a large swath of ARIA content attributes to be enumerated:

  • aria-atomic
  • aria-autocomplete
  • aria-busy
  • aria-checked
  • aria-current
  • aria-disabled
  • aria-expanded
  • aria-haspopup
  • aria-hidden
  • aria-invalid
  • aria-live
  • aria-modal
  • aria-multiline
  • aria-multiselectable
  • aria-orientation
  • aria-pressed
  • aria-readonly
  • aria-required
  • aria-selected
  • aria-sort

Doing so will have many benefits including:

  • Easier authoring: Authors benefit from normalized, spec-defined values for attributes that better align with HTML's reflection framework.
  • Validation and error handling: Browsers normalize invalid and missing values to known defaults.
  • Feature detection: Developers and user agent implementors can reliably check for supported keywords, and easily provide fallback behavior (e.g., a new diagonal value for aria-orientation would return either diagonal or the invalid value default).
  • Spec alignment and interoperability: Ensure all browsers handle values the same way.
  • Support accessibility: Support greater flexibility for accessibility APIs that handle validation downstream.
  • Reduce ambiguity around "undefined": Clarify what happens for "undefined" literal string value assignment, as opposed to an Undefined state (i.e., null).
  • More exhaustive testing via WPT: Enables complete test coverage with known permissible values.
  • Support future ARIA spec work: New ARIA content attributes will benefit from clear direction in IDL behavior.

Enumerated ARIA Attribute Definitions

Here's a table for all the updated attributes, with keyword, states, and missing/invalid default states:

Content Attribute IDL Attribute Keywords → States Missing Value Default Invalid Value Default Notes
aria-atomic ariaAtomic "true" → True
"false" → False
null False Empty string ("") → False
aria-autocomplete ariaAutoComplete "inline" → Inline
"list" → List
"both" → Both
"none" → None
None None
aria-busy ariaBusy "true" → True
"false" → False
False False Empty string ("") → False
aria-checked ariaChecked "true" → True
"false" → False
"mixed" → Mixed
Undefined (null) Undefined (null) Empty string ("") → Undefined (null)
aria-current ariaCurrent "page" → Page
"step" → Step
"location" → Location
"date" → Date
"time" → Time
"true" → True
"false" → False
False True Empty string ("") → False
aria-disabled ariaDisabled "true" → True
"false" → False
False False Empty string ("") → False
aria-expanded ariaExpanded "true" → True
"false" → False
Undefined (null) Undefined (null) Empty string ("") → Undefined (null)
aria-haspopup ariaHasPopup "true" → True
"false" → False
"menu" → Menu
"dialog" → Dialog
"listbox" → Listbox
"tree" → Tree
"grid" → Grid
null False
aria-hidden ariaHidden "true" → True
"false" → False
False False Empty string ("") → False
aria-invalid ariaInvalid "true" → True
"false" → False
"spelling" → Spelling
"grammar" → Grammar
False True Empty string ("") → False
aria-live ariaLive "polite" → Polite
"assertive" → Assertive
"off" → Off
Off Off
aria-modal ariaModal "true" → True
"false" → False
False False Empty string ("") → False
aria-multiline ariaMultiLine "true" → True
"false" → False
False False Empty string ("") → False
aria-multiselectable ariaMultiSelectable "true" → True
"false" → False
False False Empty string ("") → False
aria-orientation ariaOrientation "horizontal" → Horizontal
"vertical" → Vertical
Undefined (null) Undefined (null) Empty string ("") → Undefined (null)
aria-pressed ariaPressed "true" → True
"false" → False
"mixed" → Mixed
Undefined (null) Undefined (null) Empty string ("") → Undefined (null)
aria-readonly ariaReadOnly "true" → True
"false" → False
False False Empty string ("") → False
aria-required ariaRequired "true" → True
"false" → False
False False Empty string ("") → False
aria-selected ariaSelected "true" → True
"false" → False
Undefined (null) Undefined (null) Empty string ("") → Undefined (null)
aria-sort ariaSort "ascending" → Ascending
"descending" → Descending
"other" → Other
"none" → None
None None

FAQs

How is the empty string being treated for enumerated ARIA attributes?

Some attributes allow an empty string assignment which can map to a False state ("false") or Undefined state (null). Note that enumerated ARIA content attributes with "true"/"false" as keywords are boolean-like but do not behave the same way as HTML boolean attributes.

For example, <button disabled=""> evaluates to true for the disabled IDL attribute, whereas <button aria-disabled=""> evaluates to "false" for the ariaDisabled IDL attribute.

How is the "undefined" string being treated for enumerated ARIA attributes? Which attributes support this in ARIA spec, and how does this differ from undefined the value?

When the following ARIA attributes are assigned a literal string value of "undefined", they map to values that align with ARIA spec and the intent of authors:

  • aria-checked: "undefined" maps to Undefined state (null)
  • aria-expanded: "undefined" maps to Undefined state (null)
  • aria-hidden: "undefined" maps to False state
  • aria-orientation: "undefined" maps to Undefined state (null)
  • aria-pressed: "undefined" maps to Undefined state (null)
  • aria-selected: "undefined" maps to Undefined state (null)

For more details, please see the new section in ARIA PR #2484 titled "Relationship Between the Undefined State and "undefined" String Value".

What is the purpose of a "canonical keyword"?

Where multiple keywords map to a single state, the canonical keyword is the keyword that is returned for reflection purposes. For example, if an enumerated attribute maps the keywords "false" and the empty string to the False state, the canonical keyword would likely be "false".

See HTML Keywords and enumerated attributes.

What about ARIA content attributes that are numeric? Should their IDL attributes be numeric rather than string-reflect?

Ensuring that attributes reflect as the best possible type is beneficial for authors thus, a similar exercise could be performed for improving numeric ARIA attributes.

Although changing the IDL type of numeric ARIA attributes (such as DOMString? to long) is not possible due to webcompat, the ARIA WG could explore providing numeric IDL counterparts to existing numeric attributes. For example:

Content Attribute IDL Attribute Type
aria-colcount ariaColCount DOMString?
🆕 ariaColCountNumeric Long
aria-colindex ariaColIndex DOMString?
🆕 ariaColIndexNumeric Unsigned Long
aria-colspan ariaColSpan DOMString?
🆕 ariaColSpanNumeric Unsigned Long
aria-level ariaLevel DOMString?
🆕 ariaLevelNumeric Unsigned Long
aria-posinset ariaPosInSet DOMString?
🆕 ariaPosInSetNumeric Unsigned Long
aria-rowcount ariaRowCount DOMString?
🆕 ariaRowCountNumeric Long
aria-rowindex ariaRowIndex DOMString?
🆕 ariaRowIndexNumeric Long
aria-rowspan ariaRowSpan DOMString?
🆕 ariaRowSpanNumeric Long
aria-setsize ariaSetSize DOMString?
🆕 ariaSetSizeNumeric Long

1.3 Planning

Tracking issue: FPWD

Clone this wiki locally