The HTML aria-owns attribute
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
<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
orderproperty 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?
Does aria-owns change the DOM?
parentElement, CSS selectors and contains() checks still report its original position, and events still bubble through its DOM ancestors.






















