Skip to main content

JavaScript Events

JavaScript Page Load Events

Written by Published

DOMContentLoaded and load tell you when the page is ready to work with.

A script that runs too early cannot find the elements it needs.

These events say when it is safe to start.

Example

Example

javascript

document.addEventListener("DOMContentLoaded", function () {
  console.log("the HTML is ready");
});

document.dispatchEvent(new Event("DOMContentLoaded"));

On a real page the browser fires this itself.

The Two Events

DOMContentLoaded fires when the HTML is parsed and the DOM is built.

load fires later, once images and stylesheets have finished too.

DOMContentLoaded is the one you usually want.

Syntax

Syntax

javascript

document.addEventListener("DOMContentLoaded", handler);
window.addEventListener("load", handler);

DOMContentLoaded is on document; load is on window.

The Problem

A script in the head runs before the body has been parsed.

Any element it looks for is still missing.

Example

Example

javascript

document.body.innerHTML = "";

const missing = document.getElementById("later");

console.log(missing === null ? "not built yet" : "found");

getElementById returned null.

Waiting for the DOM

Everything inside the handler runs once the elements exist.

Example

Example

javascript

document.addEventListener("DOMContentLoaded", function () {
  document.body.innerHTML = '<p id="demo">Ready</p>';
  console.log(document.getElementById("demo").textContent);
});

document.dispatchEvent(new Event("DOMContentLoaded"));

The element was there by the time the handler ran.

load Waits for Everything

Use it only when you need images to have finished, such as measuring one.

Example

Example

javascript

window.addEventListener("load", function () {
  console.log("images and styles are done too");
});

window.dispatchEvent(new Event("load"));

load can be much later than DOMContentLoaded on a heavy page.

The Simpler Alternatives

A script at the end of the body already has the whole DOM available.

defer on a script in the head does the same thing.

Example

Example

javascript

document.body.innerHTML = '<p id="demo">Already here</p>';

console.log(document.getElementById("demo").textContent);

With defer or a script at the end, no event is needed.

A Listener Added Too Late

If the event has already happened, your handler never runs.

document.readyState lets you check.

Example

Example

javascript

console.log(document.readyState === "loading" ? "still loading" : "already done");

Values are loading, interactive and complete.

Complete Example

Complete Example

html

<!DOCTYPE html>
<html>
<head>
  <title>JavaScript Page Load Events</title>
  <script>
    document.addEventListener("DOMContentLoaded", function () {
      document.getElementById("out").textContent = "The DOM is ready";
    });

    window.addEventListener("load", function () {
      document.getElementById("out").textContent += " and everything has loaded";
    });
  </script>
</head>
<body>

  <h1>Page Load Events</h1>

  <p id="out"></p>

</body>
</html>

Try It Yourself

Run the above example in the Try It Editor.

Try removing the wrapper:

Take the code out of the listener and watch it fail to find the element.

Important Points

  • DOMContentLoaded fires when the HTML has been parsed.
  • load fires once images and styles are done as well.
  • DOMContentLoaded is on document, load is on window.
  • A script at the end of the body needs neither.
  • document.readyState says how far along the page is.

Conclusion

These events solve the oldest problem in browser JavaScript: running too early.

Modern code often avoids them with defer or a script at the end.

Knowing them still matters, because you will meet them everywhere.