demo · v135
ARIA across shadow boundaries
The web components use case the AOM explainer was designed for: a custom element's internal input needs to be labelled by a paragraph in the light DOM. IDs don't cross shadow boundaries, so the old aria-labelledby="some-id" pattern was broken by design. Element reflection lets the component pass a real element reference through — shadow walls become transparent for accessibility wiring.
aria*Elements: ?
light DOM (your page)
"Enter your full legal name as it appears on your passport."
"Required for ticket issuance — cannot be changed later."
inside the shadow root
the code
customElements.define("my-text-field", class extends HTMLElement {
connectedCallback() {
this.attachShadow({ mode: "open", delegatesFocus: true })
.innerHTML = `<label>Passenger<br><input></label>`;
this._input = this.shadowRoot.querySelector("input");
}
set labelledBy(elements) { this._input.ariaLabelledByElements = elements; }
set describedBy(elements) { this._input.ariaDescribedByElements = elements; }
});
// In page code — pass references across the shadow boundary.
field.labelledBy = [helpOne];
field.describedBy = [helpOne, helpTwo];
see also
- Element Reflection — feature index
- aria*Elements live — same-root demo
- ChromeStatus entry
- AOM explainer