References

Beginner-friendly references for web development, with live, editable examples.

The HTML aria-owns attribute

ARIA Accessibility
In short

With aria-owns, an element adopts others as children in the accessibility tree while the DOM stays as it is. List their ids in the value, and give each owned element one owner. It suits markup you can't nest, such as a popup submenu that can't sit inside its parent menu.

Overview

The aria-owns attribute declares a parent and child relationship that the DOM hierarchy can't represent. It's a global attribute whose value lists one or more ids, and those elements count as children of the element that carries it.

This attribute reshapes the accessibility tree, which browsers build from the DOM for assistive technology. In that tree, a role="tab" outside its tablist leaves its old parent and becomes a child of the tablist that owns it.

Platforms differ in how far that goes. UI Automation exposes owned elements as children, while IAccessible2 and ATK may use parent and child relations instead.

Child order follows one rule. DOM children come first, then owned elements in the order listed. A DOM child named in the value counts as owned, so it moves after its unlisted siblings and takes its place in the listed order.

When a toolbar owns a button placed after an outside button in the DOM, Tab reaches the outside button before the owned one, following DOM order, though the tree lists the owned button inside the toolbar. Manage focus so that the visual focus order matches the reading order.

Syntax

<div id="tabs" role="tablist" aria-label="Account" aria-owns="tab-3">
  <button role="tab">Profile</button>
  <button role="tab">Billing</button>
</div>
<div id="overflow-tray">
  <button id="tab-3" role="tab">Team</button>
</div>

Values

Value
A space-separated list of element id values.

Example

Live example
<p style="margin:0 0 8px">Lift the task. The script moves it to the drag layer in the DOM and sets aria-owns, which keeps it in the list's accessibility tree, after the tasks still there.</p>
<div id="board" role="list" aria-label="Sprint tasks">
  <div id="task-1" role="listitem">Write the brief</div>
  <div id="task-2" role="listitem">Design the page</div>
  <div id="task-3" role="listitem">Ship the release</div>
</div>
<div id="drag-layer" style="min-height:1.4em;margin:8px 0;border:1px dashed #767676"></div>
<button id="lift" type="button">Lift Design the page</button>
<p id="state" role="status" style="margin:8px 0 0"></p>
<script>
const board = document.getElementById('board');
const layer = document.getElementById('drag-layer');
const task = document.getElementById('task-2');
const lift = document.getElementById('lift');
const state = document.getElementById('state');

function report() {
  const owned = board.getAttribute('aria-owns') || 'not set';
  state.textContent = 'DOM parent: #' + task.parentElement.id + '. aria-owns: ' + owned + '.';
}
lift.addEventListener('click', () => {
  if (task.parentElement === board) {
    layer.append(task);
    board.setAttribute('aria-owns', 'task-2');
    lift.textContent = 'Drop Design the page';
  } else {
    board.insertBefore(task, document.getElementById('task-3'));
    board.removeAttribute('aria-owns');
    lift.textContent = 'Lift Design the page';
  }
  report();
});
report();
</script>

Best practices

  • Restructure the DOM before you reach for aria-owns. Leave it out when the DOM already represents the relationship, because it's no replacement for the hierarchy.
  • Leave reordering to the DOM instead of rearranging existing children with aria-owns. When the CSS order property changes the visual order, avoiding both it and aria-owns is the best option.
  • Count owned elements toward role rules. A tab must be contained in or owned by a tablist, so ownership can meet that requirement when nesting isn't possible.
  • Avoid circular references. The WAI-ARIA 1.3 draft forbids them and lets browsers ignore some references to build a consistent tree.

Frequently asked questions

When is aria-owns the right choice?
Use aria-owns when elements belong together on screen but can't be nested in the DOM. One case is a submenu shown near its parent menu but kept out of it in the DOM, because nesting would affect the visual presentation.
Does aria-owns change the DOM?
No, aria-owns leaves the DOM alone. The owned element's parentElement, CSS selectors and contains() checks still report its original position, and events still bubble through its DOM ancestors.
Can two elements own the same id with aria-owns?
No, naming one id in two aria-owns attributes is an author error, since an element gets one explicit owner. Only the first relationship found is supposed to count, but which owner Chrome keeps varies with the page, so don't rely on either.
Is aria-owns exposed to VoiceOver?
VoiceOver may not expose aria-owns before iOS 17.3 and macOS 14.3. Test on those versions if you support them.
Does aria-owns resolve to a hidden element?
Whether aria-owns resolves depends on how the target is hidden. The WAI-ARIA 1.3 draft rules out a target hidden from all users, such as one inside a hidden element, but its own example brings in a target under aria-hidden=true, as Chrome and Firefox do.
Is aria-owns right for a menu button?
No, a menu button can point at its menu with aria-controls instead. The WAI-ARIA 1.3 draft says authors must not set aria-owns on an element with presentational children, and button is such a role, though Chrome still moves the target.
Which browsers support ariaOwnsElements for aria-owns?
Firefox 136 and Safari 16.4 support the ariaOwnsElements property, but Chrome and Edge don't. Set aria-owns with setAttribute and a string of ids, which works in all four.