v152 · web components · accessibility · shipped
Reference Target for Cross-root ARIA
Reference Target enables ID attributes like <label for>, aria-labelledby, popovertarget, and commandfor to be forwarded to elements inside a component's shadow DOM, while maintaining the shadow's encapsulation of its internal state. When a shadow host specifies an element in its shadow tree to act as its reference target, all ID references pointing to the shadow host are forwarded to the reference target element instead.
referenceTargetMap, exportid) is not implemented. Separately, aria-owns forwarding is gated behind a second runtime flag (ShadowRootReferenceTargetAriaOwns, no status — not enabled by default; WICG/webcomponents #1091). Feature-detect ("referenceTarget" in ShadowRoot.prototype) before relying on any of this cross-browser.
at a glance
| Shipped in | Chrome 152 — Enabled by default (desktop, Android, WebView; the milestone listing is authoritative, verified 2026-07-28) |
|---|---|
| Mechanism | A shadow root names one element in its tree by ID as the reference target; any IDREF (for, aria-labelledby, popovertarget, …) that points at the host resolves to that element instead |
| Three ways to set | referenceTarget in the ShadowRootInit argument to attachShadow() · the ShadowRoot.referenceTarget IDL attribute · the shadowrootreferencetarget attribute on <template> (declarative shadow DOM) — the JS surface has its own reference page → |
| Runtime flag | ShadowRootReferenceTarget in runtime_enabled_features.json5: status: "stable", origin_trial_feature_name: "ShadowRootReferenceTarget" |
| Origin trial | Chrome 133 – 135 (concluded; stage record on the ChromeStatus entry) |
| Spec status | whatwg/html #10995 + whatwg/dom #1353 — both OPEN; explainer at WICG/webcomponents; original proposal WICG/aom PR #207 |
| Vendor positions | Firefox: positive · Safari: no signal (open) · TAG review: w3ctag/design-reviews #961 (closed) |
| Intents | Intent to Prototype · Intent to Experiment (origin trial 133–135) · Intent to Ship |
| ChromeStatus | 5188237101891584 — Reference Target for Cross-root ARIA (web-feature referencetarget) |
| Bug | Chromium issue 346835896 |
why it exists
Shadow DOM encapsulation breaks IDREF-based relationships. A component that wraps a native control — the explainer's examples are a design-system <sp-checkbox> enclosing a real <input type="checkbox">, and an <md-dialog> enclosing a real <dialog> with scrim and focus-trap markup — cannot be the target of a <label for>, an aria-labelledby, or a popovertarget in any useful way: the reference points at the host, not at the internal element that actually implements the behavior. Before Reference Target, component authors had to break encapsulation (hoist IDs, duplicate ARIA onto the host and mirror state) or leave assistive technology and label activation broken. Reference Target lets the host substitute an enclosed element for exactly those IDREF purposes, and nothing else.
how forwarding works
Setting a reference target is a declaration on the shadow root: the ID of one element in the shadow tree. From then on, when the host element is the target of an IDREF attribute, the reference resolves to the reference target instead of the host. The explainer defines the intended scope as all attributes that refer to another element by ID string:
| Group | Attributes |
|---|---|
| ARIA | aria-activedescendant, aria-controls, aria-describedby, aria-details, aria-errormessage, aria-flowto, aria-labelledby, aria-owns (aria-owns is behind the separate ShadowRootReferenceTargetAriaOwns flag — see the warn-block) |
| Inputs / interactive | for (including the label's click-to-activate behavior), form, list, popovertarget, commandfor, interesttarget, anchor (the last three from the Invokers/Popover proposals) |
| Tables | headers |
References are live. The effective target is recomputed when any of the following changes (explainer, verbatim list):
- The host changes its
referenceTargetto refer to a different ID. - An element with an
idmatching the host's referenceTarget is added to or removed from the host's shadow tree. - The
idattribute of an element inside the host's shadow tree is changed to or from the referenceTarget ID. - The host is added or removed from the DOM.
- The host's
idattribute is changed.
declarative syntax
With declarative shadow DOM, the reference target is set with the shadowrootreferencetarget attribute on the <template> element — the value is the id of an element inside that template:
<label for="my-checkbox">Checkbox value (click me to toggle checkbox)</label>
<custom-checkbox id="my-checkbox">
<template shadowrootmode="open" shadowrootreferencetarget="real-checkbox">
<input id="real-checkbox" type="checkbox">
</template>
</custom-checkbox>
The label's for="my-checkbox" points at the host, but activation, accessibility computation, and HTMLInputElement.labels all treat the enclosed <input id="real-checkbox"> as the labeled control. The same value can be read back via the HTMLTemplateElement.shadowRootReferenceTarget IDL reflection (on the JS surface page: ShadowRoot.referenceTarget & friends →).
interaction contracts and edge cases
| CSS selectors | Unaffected. An ID selector matches the host element carrying the id — never the reference target inside the shadow tree |
|---|---|
| Form-associated custom elements | A FACE already supports being the target of <label for>; if it has a reference target, the label applies to the target instead. No other FACE behavior changes |
Host nested in <label> | Implicit association works: the reference target becomes the labeled control of the enclosing label (the explainer's <fancy-input> example) |
Host nested in <form> | No change: the target element is not implicitly associated with the form unless the host is a form-associated custom element |
| Element-reflecting JS attributes | ariaControlsElements, ariaLabelledByElements, popoverTargetElement, HTMLLabelElement.control, and siblings return the host element, never the reference target inside the shadow tree — an IDL attribute of type Element can only refer to a descendant of a shadow-including ancestor of the element hosting the attribute. (HTMLInputElement.form/.list are specced to narrower types and need spec updates to return the host — noted in the explainer as open.) |
labels APIs | HTMLInputElement.labels on the internal input returns all forwarded labels in shadow-including tree order. ElementInternals.labels on a form-associated host with a reference target returns [] — every label is forwarded, none stays associated with the host |
| Event retargeting | Unaffected — Reference Target changes IDREF resolution only. The WPT suite includes event-path.html coverage confirming event paths behave normally |
| Serialization | Declarative roots serialize the attribute: getHTML({serializableShadowRoots: true}) emits shadowrootreferencetarget (WPT gethtml-serialization.html) |
| Unknown / missing target ID | Not an error. Resolution is an ID lookup in the shadow tree at reference-lookup time; while nothing matches, forwarding has no target — and because references are live, it starts resolving as soon as a matching element exists (details: JS surface — errors) |
relationship to ARIA Element reflection (aria-actions & friends)
Reference Target composes with — but does not replace — the ARIA Element-reflection family (ariaLabelledByElements, ariaControlsElements, and Chrome 151's ariaActionsElements). The two mechanisms answer different questions: Element reflection lets script assign target elements by reference instead of by ID string (and, per the interaction contract above, those getters return the host when forwarding is in play); Reference Target lets a component author decide where IDREFs that point at the host should land inside its shadow tree. A page can use both: el.ariaControlsElements = [fancyListboxHost] targets the host by reference, and the host's referenceTarget forwards the resulting AT relationship to the internal listbox.
examples
Imperative setup (the explainer's sp-checkbox, closed root):
class Checkbox extends HTMLElement {
constructor() {
super();
const root = this.attachShadow({ mode: "closed", referenceTarget: "input" });
root.innerHTML = `<input id="input" type="checkbox">`;
}
}
customElements.define("sp-checkbox", Checkbox);
// <label for="consent"> + <sp-checkbox id="consent"> — the label now
// labels the internal input: click activation, accName, and input.labels all work.
The Chrome Platform Showcase feature page for Reference Target (HEAD-checked 200, 2026-07-28) hosts the interactive demos; there is no concept sub-route to embed yet, so this page links rather than iframes. The Microsoft Edge reference-target demo (from the ChromeStatus sample links) is a second live example.
Source: WICG explainer — sp-checkbox example; chrome-platform-showcasebrowser compatibility
| Engine | Support | Notes |
|---|---|---|
| Chrome / Edge | 133 (flag) → 152 enabled by default | BCD records 133 behind #enable-experimental-web-platform-features and has not yet recorded the default-on milestone (freshness gap, checked 2026-07-28); the milestone=152 listing files it Enabled by default. Origin trial ran 133–135 |
| Firefox | 144 behind a flag | BCD: dom.shadowdom.referenceTarget.enabled; standards position positive |
| Safari | 26 behind flags | BCD lists two preferences: referenceTarget and referenceTarget support for aria-owns; standards position: no signal (open) |
| BCD status | experimental: true on both BCD entries (api/ShadowRoot.json, html/elements/template.json) — treat the whole surface as experimental outside Chrome 152+ | |
| WPT | 15 test files in shadow-dom/reference-target/tentative (all mapped to the referencetarget web-feature via WEB_FEATURES.yml): basics, label-for, label-descendant, form, popovertarget, commandfor, interestfor, aria-labelledby, dom-mutation, event-path, gethtml-serialization, property-reflection ×3, shadowrootreferencetarget-idl-reflection. Per-run pass counts not captured at fetch time (wpt.fyi dashboard) | |
security and privacy
Reference Target preserves shadow encapsulation rather than weakening it: outside pages learn only that IDREFs to the host resolve to some internal element, not which one — Element-reflecting JavaScript getters (ariaControlsElements, HTMLLabelElement.control, …) return the host, never the internal target, so shadow-internal element references cannot leak out through script (see interaction contracts). CSS selectors and event retargeting are unaffected. No new storage, network, or fingerprinting surface is introduced in the sources read.
specifications
| Specification | Status |
|---|---|
| whatwg/html PR #10995 — Add reference target | OPEN (verified 2026-07-28) |
| whatwg/dom PR #1353 | OPEN (linked from the webstatus feature record) |
| WICG/webcomponents — Reference Target explainer | Community-group explainer; the design document this page follows |
see also
- gendn — ShadowRoot.referenceTarget, ShadowRootInit.referenceTarget, and the template reflection (JS surface)
- gendn v151 — aria-actions (ARIA Element reflection family)
- gendn v151 — shadowrootslotassignment (sibling declarative-shadow-DOM attribute)
- blink-dev — Intent to Ship: Reference Target
- W3C TAG design review #961
- WICG/webcomponents #1091 — referenceTarget support for aria-owns
- Chromium tracking bug 346835896
- Chrome Platform Showcase — this feature · Microsoft Edge demo