The DOMContentLoaded
event fires when the HTML document has been completely parsed, and all deferred scripts (<script defer src="…">
and <script type="module">
) have downloaded and executed. It doesn't wait for other things like images, subframes, and async scripts to finish loading.
DOMContentLoaded
does not wait for stylesheets to load, however deferred scripts do wait for stylesheets, and the DOMContentLoaded
event is queued after deferred scripts. Also, scripts which aren't deferred or async (e.g. <script>
) will wait for already-parsed stylesheets to load.
A different event, load
, should be used only to detect a fully-loaded page. It is a common mistake to use load
where DOMContentLoaded
would be more appropriate.
This event is not cancelable.
Use the event name in methods like addEventListener()
, or set an event handler property.
addEventListener("DOMContentLoaded", (event) => {});
onDOMContentLoaded = (event) => {};
document.addEventListener("DOMContentLoaded", (event) => {
console.log("DOM fully loaded and parsed");
});
<script>
document.addEventListener("DOMContentLoaded", (event) => {
console.log("DOM fully loaded and parsed");
});
for (let i = 0; i < 1_000_000_000; i++);
</script>
DOMContentLoaded
may fire before your script has a chance to run, so it is wise to check before adding a listener.
function doSomething() {
console.info("DOM loaded");
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", doSomething);
} else {
doSomething();
}
Note: There's no race condition here — it's not possible for the document to be loaded between the if
check and the addEventListener()
call. JavaScript has run-to-completion semantics, which means if the document is loading at one particular tick of the event loop, it can't become loaded until the next cycle, at which time the doSomething
handler is already attached and will be fired.
HTML
<div class="controls">
<button id="reload" type="button">Reload</button>
</div>
<div class="event-log">
<label for="eventLog">Event log:</label>
<textarea
readonly
class="event-log-contents"
rows="8"
cols="30"
id="eventLog"></textarea>
</div>
JavaScript
const log = document.querySelector(".event-log-contents");
const reload = document.querySelector("#reload");
reload.addEventListener("click", () => {
log.textContent = "";
setTimeout(() => {
window.location.reload(true);
}, 200);
});
window.addEventListener("load", (event) => {
log.textContent += "load\n";
});
document.addEventListener("readystatechange", (event) => {
log.textContent += `readystate: ${document.readyState}\n`;
});
document.addEventListener("DOMContentLoaded", (event) => {
log.textContent += "DOMContentLoaded\n";
});
Result