ElementInternals: labels property
Baseline
Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2023.
The labels read-only property of the ElementInternals interface returns the labels associated with the element.
Value
A NodeList containing all of the label elements associated with this element.
Exceptions
NotSupportedErrorDOMException-
Thrown if the element does not have its
formAssociatedproperty set totrue.
Accessibility concerns
A <label> associated with a form-associated custom element is exposed to assistive technology in the same way as a label on a built-in form control.
In Chrome and Firefox it provides the accessible name for the element.
For a screen reader to reach that name, the element also has to be focusable.
A custom element is not focusable by default.
It needs a tabindex attribute, or a shadow root created with delegatesFocus: true and a focusable element inside it.
Safari does not expose the label this way.
VoiceOver does not read a <label> linked to a form-associated custom element (WebKit bug 259124).
An element that relies on the label association alone therefore has no accessible name in Safari.
To give the element an accessible name in every browser, set ariaLabel on the element's internals as well as associating the label:
class CustomCheckbox extends HTMLElement {
static formAssociated = true;
constructor() {
super();
this.internals_ = this.attachInternals();
this.internals_.role = "checkbox";
this.internals_.ariaLabel = "Join newsletter";
}
}
Note:
Setting ariaLabel on the internals defines a default semantic for the element.
An aria-label attribute set on the element itself takes precedence over it, which lets a page author override the name without the component losing its own fallback.
Examples
The following example shows a custom checkbox component with a <label> element linked to it.
Printing the value of labels to the console returns a NodeList with one entry, representing this label.
<form id="myForm">
<custom-checkbox id="custom-checkbox" tabindex="0"></custom-checkbox>
<label for="custom-checkbox">Join newsletter</label>
</form>
class CustomCheckbox extends HTMLElement {
static formAssociated = true;
constructor() {
super();
this.internals_ = this.attachInternals();
}
// …
}
window.customElements.define("custom-checkbox", CustomCheckbox);
const element = document.getElementById("custom-checkbox");
console.log(element.internals_.labels); // NodeList [ label ]
Note:
A label is only included in labels once it has been parsed.
Reading labels from connectedCallback() returns an empty NodeList when the associated <label> comes after the element in the source, because the parser has not reached it yet.
Specifications
| Specification |
|---|
| HTML> # dom-elementinternals-labels> |