Signatur
Beschreibung
Die schreibgeschützte Eigenschaft labels liefert alle <label>-Elemente, die ein bestimmtes Eingabefeld beschriften. Ein Label ist auf zwei Wegen mit einem Feld verknüpft: explizit über das Attribut for, dessen Wert der id des Feldes entspricht, oder implizit, wenn das Feld innerhalb des <label> steht und das erste beschriftbare Element darin ist.
Zurück kommt eine NodeList in Dokumentreihenfolge. Diese Liste ist live: Kommen Labels im DOM hinzu, werden sie entfernt oder ändern sich for- bzw. id-Attribute, passt sich die Liste von selbst an. Außerdem gibt die Eigenschaft bei jedem Zugriff dasselbe Objekt zurück. Ein Feld darf mehrere Labels haben, zum Beispiel eine sichtbare Beschriftung und einen zusätzlichen Hinweistext.
Praktisch ist labels vor allem, wenn du zum Feld den passenden Beschriftungstext brauchst: für Fehlermeldungen bei der Formularprüfung, um Labels optisch hervorzuheben, für Tests zur Barrierefreiheit oder um Formulare automatisch auszuwerten. Du musst dafür nicht selbst per querySelector('label[for=…]') suchen, und implizit verknüpfte Labels werden auch erfasst.
Ist das Feld vom Typ hidden, gibt labels null zurück, weil versteckte Felder nicht beschriftet werden können. Dieselbe Eigenschaft gibt es auch bei anderen beschriftbaren Elementen, etwa HTMLSelectElement, HTMLTextAreaElement, HTMLButtonElement, HTMLOutputElement, HTMLMeterElement und HTMLProgressElement.
Rückgabewert
NodeList mit allen verknüpften <label>-Elementen in Dokumentreihenfolge. Gibt es kein Label, ist die Liste leer (length === 0). Bei <input type="hidden"> ist der Wert null.Beispiele
Explizite und implizite Labels auslesen
// HTML:
// <label for="email">E-Mail-Adresse</label>
// <label>Newsletter <input id="news" type="checkbox"></label>
// <input id="email" type="email">
// <label for="email">(wird nicht weitergegeben)</label>
const email = document.getElementById('email');
const news = document.getElementById('news');
console.log(email.labels.length);
console.log([...email.labels].map((l) => l.textContent.trim()));
console.log(news.labels[0].textContent.trim());
Fehlermeldung mit dem Label-Text bei der Formularprüfung
// Liefert einen lesbaren Feldnamen, sonst name oder id als Ersatz
const getFieldName = (input) => {
const label = input.labels?.[0];
return label ? label.textContent.trim() : input.name || input.id;
};
const form = document.querySelector('form');
form.addEventListener('submit', (event) => {
const invalid = [...form.querySelectorAll('input')].filter(
(input) => !input.checkValidity()
);
if (invalid.length > 0) {
event.preventDefault();
// Labels der ungültigen Felder markieren
invalid.forEach((input) =>
input.labels?.forEach((l) => l.classList.add('fehler'))
);
alert(`Bitte prüfen: ${invalid.map(getFieldName).join(', ')}`);
}
});
Versteckte Felder und live aktualisierte Liste
const hidden = document.createElement('input');
hidden.type = 'hidden';
console.log(hidden.labels); // null
const field = document.createElement('input');
field.id = 'plz';
document.body.append(field);
const list = field.labels; // live NodeList
console.log(list.length);
const label = document.createElement('label');
label.htmlFor = 'plz';
label.textContent = 'Postleitzahl';
document.body.prepend(label);
console.log(list.length); // Liste hat sich angepasst
console.log(list === field.labels); // immer dasselbe Objekt
Labels bei Fokus hervorheben
document.querySelectorAll('input:not([type=hidden])').forEach((input) => {
input.addEventListener('focus', () => {
input.labels.forEach((l) => l.classList.add('aktiv'));
});
input.addEventListener('blur', () => {
input.labels.forEach((l) => l.classList.remove('aktiv'));
});
});
// Wichtig · Fallstricke
- Auf
nullprüfen: Beitype="hidden"gibtlabelsnullstatt einer leeren Liste zurück. Ein direkter Aufruf wieinput.labels.forEach(…)wirft dann einenTypeError. Verwende Optional Chaining (input.labels?.forEach(…)) oder filtere versteckte Felder vorher heraus. - Die Liste ist live: Wenn du über die Liste läufst und dabei Labels entfernst oder
for-Attribute änderst, verschieben sich die Einträge. Kopiere die Liste in diesem Fall vorher mit[...input.labels]oderArray.from(). - Nur ein Teil des zugänglichen Namens:
aria-labelundaria-labelledbytauchen inlabelsnicht auf. Wenn du den vollständigen zugänglichen Namen brauchst, musst du diese Attribute selbst mit auswerten. - Implizite Labels: Ein umschließendes
<label>beschriftet nur das erste beschriftbare Element darin. Hat das Label außerdem einfor-Attribut, gilt nurfor. - Nur mit Dokument oder gemeinsamem Baum: Die Verknüpfung über
for/idgilt nur innerhalb desselben Baums. Labels außerhalb eines Shadow DOM werden nicht erfasst. Bei Feldern, die nicht im Dokument eingehängt sind, sind nur implizite Labels im selben Teilbaum enthalten. - Kompatibilität: Wird von allen modernen Browsern unterstützt (Chrome, Edge, Firefox ab Version 56, Safari). Der Internet Explorer kennt die Eigenschaft nicht. Dort hilft nur die manuelle Suche per
querySelectorAll('label[for="…"]')plusclosest('label').