Max Design

Published:

A single sentence with a lot of impact

Some ARIA roles can completely remove their children’s semantics.

This behaviour is defined in the Core Accessibility API Mappings 1.2 specification:

If the host language element is overridden by a WAI-ARIA role whose semantics or structure is not equivalent to the native host language semantics or to a subclass of those semantics, then treat any child elements having roles specified as Allowed Accessibility Child Roles as having presentation or none.

Source

Here’s a plain language breakdown of that sentence:

In these cases, ARIA doesn’t build on existing semantics. It replaces the entire semantic model of the element, including how the browser interprets its children.

Once this happens, the browser no longer makes any assumptions about native HTML relationships. Every meaningful part of the widget must be stated explicitly using ARIA roles.


Is this documented anywhere else?

This rule appears in other specifications, but only indirectly. It’s never stated as clearly as it is in Core AAM. For example:

5.2.6 Allowed Accessibility Child Roles

Explains which child roles are allowed, but not what happens if they’re missing.

5.2.7 Required Accessibility Parent Role

Defines structural expectations, but not the consequence of breaking them.


An example: menu and menuitem

Let’s look at an example:

<ul role="menu">
  <li>Save</li>
  <li>Open</li>
</ul>

At a glance, this looks reasonable.

However, this is not how ARIA works.

By applying role="menu", you’re opting into the ARIA menu widget model whether you intend to or not.

If you inspect this example in Chrome’s accessibility tree, you can see how the list items lose their semantics and are not exposed as menu items.

From an accessibility perspective, this is now a menu with no items.

To make this work, the child semantics must be redefined explicitly:

<ul role="menu">
  <li role="menuitem">Save</li>
  <li role="menuitem">Open</li>
</ul>

This is required to rebuild the menu’s structure in the accessibility tree.


Other common examples where child semantics are wiped

The menu example is not unique. The same kind of structural replacement happens with many widget roles.

Here are some other examples:

In all of these cases, native HTML semantics may be ignored once the ARIA widget role is applied.


When this rule does not apply

So far, this article has shown how some ARIA roles replace an element’s entire semantic structure and wipe out native child semantics.

However, there is an important exception. The specification includes a qualifying phrase that is easy to miss:

“…whose semantics or structure is not equivalent to the native host language semantics…”

Those few words carry a lot of weight. They define when ARIA replaces semantics and when it merely reinforces them.

Here are two rules to help understand what is happening:

When the ARIA role introduces a different widget model, native structure is discarded. It must be rebuilt explicitly using ARIA roles.

However, when the child elements already have native semantics that match the ARIA role’s expected model, those semantics are preserved.

Here’s an example where semantics are preserved:

<div role="radiogroup" aria-labelledby="group-heading">
  <h3 id="group-heading">Do you like boats?</h3>
  <div>
    <input type="radio" id="boats-y" name="boats">
    <label for="boats-y">Yes</label>
  </div>
  <div>
    <input type="radio" id="boats-n" name="boats">
    <label for="boats-n">No</label>
  </div>
</div>

In this case, the child elements already match the radiogroup model. So, ARIA is reinforcing an existing model rather than replacing it:

The radio buttons remain intact and correctly exposed to assistive technologies.

Here’s a similar example where semantics are not preserved:

<div role="radiogroup">
  <div>Yes</div>
  <div>No</div>
</div>

In this case, the child elements do not expose role="radio" and do not match the expected radiogroup model.

Because the semantics are not equivalent, the exception no longer applies. The radiogroup role introduces a new widget model, and the child semantics are discarded.

To make this accessible, the child roles would need to be redefined explicitly.

<div role="radiogroup">
  <div role="radio">Yes</div>
  <div role="radio">No</div>
</div>

Note: This example is not a complete or accessible radio group. It omits keyboard support, state management, and interaction logic, and is shown only to demonstrate how child roles would need to be redefined.

Why this distinction matters

Without this context, ARIA can feel inconsistent.

Sometimes ARIA roles seem to wipe child semantics, and at other times they do not.

This difference isn’t arbitrary. It depends on whether the ARIA role introduces a new widget model or aligns with an existing native one.

Once you recognise this distinction, a lot of previously confusing ARIA behaviour starts to make sense.


Conclusion

Understanding which ARIA roles replace structure, and which merely reinforce it, is important. Especially when building non-native widgets.

Related articles

How aria-labelledby really works

How aria-labelledby works, including naming precedence, multiple references, hidden content, broken IDs, and shadow DOM boundaries.

Tests for aria-labelledby and aria-describedby

A series of tests to determine how hidden content is used by aria-labelledby and aria-describedby.

Eight quick things to remember when using aria-owns

Eight quick things to rememer when using aria-owns including what it is, when to use it and when not to use it.

Why role="button" on a <button> does nothing

Adding role="button" to a native <button> looks harmless, but it doesn’t change anything. This article explains why that ARIA role is ignored and how this behaviour is defined in the specification.