DOMContentLoaded – HTML DOM vollständig geladen?
DOMContentLoaded feuert, sobald das Dokument vollständig geladen und geparst ist, aber wartet nicht auf das Laden von externen Medien und Dateien wie CSS, Bildern, Bannern und iframes wie das load-Event. Wenn das DOM geladen und geparst ist, können DOM-Elemente abgefragt, addEventListener gesetzt, Inhalte eingesetzt werden.
DOMContentLoaded im Head-Element der Seite
Das DOM ist noch nicht geladen, wenn das Script im head geparst wird. Elemente, auf die ein Zugriff erfolgen soll, existieren also noch nicht. Die Browser haben ein Event DOMContentLoaded, das feuert, wenn das DOM geladen ist und vom Script durchquert werden kann.
document.addEventListener ("DOMContentLoaded", () => {
const marker = document.querySelector(".marker");
marker.innerHTML = "DOM geladen";
marker.addEventListener ("click", () => {
marker.innerHTML = "Button aktiviert";
});
});
DOMContentLoaded sollte abgefragt werden, wenn Scripte im head-Element der Seite geladen werden. Heute gibt es zwar intuitivere Methoden, um Scripte effizient zu laden: das defer- oder async-Attribut im <script>-Tag, aber es gilt als gute Programmierpraxis, das DOM erst nach dem Laden zu manipulieren.
Der Script-Aufruf mit defer ist Äquivalent zu DOMContentLoaded, braucht aber keinen Event-Listener. Mit dem async-Attribut lädt der Browser das Skript parallel zum HTML-Parsen und führt es sofort aus, sobald es fertig ist. Dabei ist allerdings die Reihenfolge der Script-Aufrufe nicht garantiert.Wann ist das Bild geladen?
Das Laden von CSS-Dateien, Bildern, Fonts und iframes blockiert die Ausführung von Scripts. Haben wir also ein <script> nach einem <link rel="stylesheet" ...>, wird die Seite nicht fertig geparst und DOMContentLoaded wird nicht feuern bis das Stylesheet geladen wurde.
<script>
document.addEventListener("DOMContentLoaded", () => {
const images = [
"neptun-2400-1600.jpg",
"berlin-2400-1600.jpg",
"florenz-2400-1600.jpg"
];
const slide = document.querySelector("#slide");
const result = document.querySelector(".result");
const time = 3000;
let index = 0;
result.textContent = "Alles geladen! Warten auf die Bilder.";
const changeImage = () => {
slide.src = images[index];
index = (index + 1) % images.length;
};
// erstes Bild sofort, dann Intervall
changeImage();
setInterval(changeImage, time);
});
</script>
In diesem Beispiel wird DOMContentLoaded ausgeführt, wenn das Dokument geladen ist, aber wartet nicht auf das Laden aller Komponenten der Seite. Alles geladen! Warten auf die Bilder. taucht also vor dem Laden der Bilder auf.
Allerdings erzwingt auch das Laden externer Scripte (mit src, aber ohne asnyc oder defer) eine Pause im Aufbau der Seite. DOMContentLoaded feuert also erst nach der Ausführung externer Scripte.
Wenn das Dokument geladen ist
DOMContentLoaded feuert, wenn das HTML vollständig geladen und der DOM-Baum aufgebaut ist, und wartet nicht auf
- ❌ Bilder,
- ❌ Hintergrundbilder,
- ❌ Fonts,
- ❌ Videos,
- ❌ iframes
DOMContentLoaded wird für einen Performance-optimierten Start bei DOM-Manipulationen, dem Einsetzen von CSS-Klassen und dem Setzen von Event-Listener eingesetzt.
defer und DOMContentLoaded passen gut zusammen. Das Skript läuft parallel zum HTML, wird direkt nach dem DOM-Aufbau ausgeführt und feuert danach garantiert. Die Reihenfolge mehrerer Skripte bleibt erhalten, das HTML sauber organisiert. Das ist also heute die empfohlene Standardlösung:
<head> … <script src="app.js" defer></script> </head>
Script app.js
document.addEventListener("DOMContentLoaded", () => {
init();
});
Das Laden des Skripts am Ende des Dokuments vor dem schließenden body-Tag ist nicht falsch, aber heute nicht mehr nötig und gilt als veraltet.
| Variante | Heute empfohlen? | Warum |
|---|---|---|
| <head> + defer | ⭐⭐⭐⭐⭐ | Best Practice |
| <head> + async | ⭐ | Nur Spezialfälle |
| Body-Ende | ⭐⭐ | Legacy, okay aber alt |
| Ohne Event + defer | ⭐⭐⭐⭐⭐ | wenn kein DOMContentLoaded nötig |
| type="module" | ⭐⭐⭐⭐⭐ | modernster Ansatz |
window.addEventListener("load", () => {})
DOMContentLoaded und CSS
Externe CSS-Dateien betreffen das DOM nicht, also wartet DOMContentLoaded nicht, bis sie geladen sind. Liegt das Script allerdings nach dem link-Tag der CSS-Datei, muss es warten bis die Stile ausgeführt wurden.