Start · Sprachen · JavaScript · Referenz · Element.closest()

Element.closest()

Methode

Durchläuft das Element selbst und dann seine Vorfahren Richtung Dokumentwurzel und gibt das erste Element zurück, das dem CSS-Selektor entspricht – sonst <code>null</code>.

seit JavaScript Baseline: alle modernen Browser (seit 2015/2016, E Kategorie: webapi

Signatur

Element.prototype.closest(selectors)

Beschreibung

closest() prüft zuerst das Element selbst und steigt dann Schritt für Schritt über parentElement nach oben, bis ein Element dem angegebenen CSS-Selektor entspricht. Das erste passende Element wird zurückgegeben. Wird bis zur Wurzel keins gefunden, ist das Ergebnis null.

Am häufigsten braucht man die Methode bei der Ereignisdelegation (Event Delegation): Ein einziger Listener sitzt auf einem Container, und mit event.target.closest('button[data-action]') findet man heraus, welches logische Element angeklickt wurde, auch wenn der Klick auf einem verschachtelten Kindelement wie einem <span> oder <svg> gelandet ist.

Die Methode ist quasi das Gegenstück zu querySelector(): querySelector() sucht abwärts in den Nachfahren, closest() sucht aufwärts in den Vorfahren. Der Selektor wird genauso ausgewertet wie bei matches() und darf deshalb komplexe Selektoren enthalten, etwa Kombinatoren, Attributselektoren und Pseudoklassen wie :not() oder :has().

Parameter

Name Typ Default Beschreibung
$selectors Pflicht string Ein gültiger CSS-Selektor oder eine kommagetrennte Selektorliste, z. B. '.card, [data-panel]'.

Rückgabewert

Typ
Element | null
Beschreibung
Das nächstgelegene passende Element. Das kann auch das Element selbst sein. Wird keins gefunden, ist der Rückgabewert null.

Beispiele

Grundlegende Suche nach Vorfahren

// HTML:
// <article class="post" id="p1">
//   <div class="content">
//     <a href="#" id="link">Weiterlesen</a>
//   </div>
// </article>

const link = document.getElementById('link');

console.log(link.closest('.post').id);     // nächstes Artikel-Element
console.log(link.closest('div').className); // nächster <div>
console.log(link.closest('a') === link);   // Element selbst zählt mit
console.log(link.closest('.sidebar'));     // nicht vorhanden
p1 content true null

Ereignisdelegation in einer Aufgabenliste

// HTML:
// <ul id="todos">
//   <li data-id="1">Einkaufen <button data-action="delete"><span>🗑</span></button></li>
//   <li data-id="2">Sport <button data-action="delete"><span>🗑</span></button></li>
// </ul>

const list = document.getElementById('todos');

list.addEventListener('click', (event) => {
  // Klick kann auf dem <span> landen, deshalb closest()
  const button = event.target.closest('button[data-action="delete"]');
  if (!button || !list.contains(button)) return;

  const item = button.closest('li');
  console.log(`Lösche Eintrag ${item.dataset.id}`);
  item.remove();
});
Lösche Eintrag 2 // nach Klick auf das Symbol im zweiten Eintrag

Klick außerhalb schließt ein Dropdown

const dropdown = document.querySelector('.dropdown');

const handleOutsideClick = (event) => {
  // Ist der Klick innerhalb eines Dropdowns gelandet?
  if (!event.target.closest('.dropdown')) {
    dropdown.classList.remove('open');
    console.log('Dropdown geschlossen');
  }
};

document.addEventListener('click', handleOutsideClick);
Dropdown geschlossen // bei Klick außerhalb

Selektorliste und ungültiger Selektor

const input = document.querySelector('input[name="email"]');

// Nächster Container, egal ob Formular oder Dialog
const container = input.closest('form, dialog, [role="dialog"]');
console.log(container?.tagName ?? 'kein Container');

try {
  input.closest('::invalid[');
} catch (err) {
  console.log(err.name);
}
FORM SyntaxError

// Wichtig · Fallstricke

  • Das Element selbst wird mitgeprüft. Wenn nur Vorfahren gesucht werden sollen, verwende el.parentElement?.closest(sel).
  • Ist selectors kein gültiger CSS-Selektor, wirft die Methode eine SyntaxError-DOMException.
  • Prüfe das Ergebnis immer auf null, bevor du darauf zugreifst. Optional Chaining (?.) hilft dabei.
  • Bei der Ereignisdelegation kann closest() auch ein Element außerhalb des Containers finden, auf dem der Listener sitzt. Das passiert, wenn der Container selbst in einem passenden Element verschachtelt ist. Prüfe das zusätzlich mit container.contains(result).
  • event.target kann ein Textknoten oder ein Nicht-Element sein, zum Beispiel document oder window bei eigenen Ereignissen. Diese haben kein closest(). Prüfe in diesem Fall vorher mit event.target instanceof Element.
  • Die Suche endet an der Grenze eines Shadow Root. Elemente im Light DOM des Hosts werden nicht gefunden.
  • Die Methode wird in allen modernen Browsern unterstützt. Der Internet Explorer kennt sie nicht; dort war ein Polyfill mit msMatchesSelector und einer Schleife über parentElement nötig.
  • Zur Laufzeit: Die Suche kostet O(Tiefe des DOM-Baums) und ist in der Praxis sehr schnell. Selektoren mit :has() können aber teuer werden.