Page event listeners: DOMContentLoaded, load, beforeunload and unload
Last updated: February 14, 2022.
Sometimes we want some code to run only when a page has reached a certain state of loading (e.g. the DOM has loaded or all resources have loaded) or when a user is exiting the page.
We can achieve this by listening out for events on the global window
object. In this tutorial, look at four such events: DOMContentLoaded
, load
, beforeunload
, unload
.
Table of contents
Page states
When a page loads, it goes through several states.
We can see the initial state of a page by logging the value of the readyState
property on the document object. And we can see state changes by listening out for the readystatechange
event on the document
object:
// Log initial state: console.log(document.readyState); // Log changes to state as page loads: document.addEventListener('readystatechange', () => console.log(document.readyState)); // Output: // (1) loading // (2) interactive // (3) complete
This produces three values. Each is fired as a page reaches different states in its loading:
loading
: The page is in an initial state of loadinginteractive
: The content of the DOM has loadedcomplete
: Resources are loaded (image sizes are known, scripts, stylesheets, etc.)
Event listeners that run some code only after a page has reached a certain state of loading are related to these events.
The DOMContentLoaded
event is triggered once the page becomes interactive. The load
event occurs after the loading of all resources is complete, including the full loading of images. This means it occurs after the value of document.readyState
changes to complete
because this happens when image sizes are known.
We can see this process by logging the values document.readyState
and something for both the DOMContentLoaded
and load
events:
// Log initial state: console.log(document.readyState); // Log changes to state as page loads: document.addEventListener('readystatechange', () => console.log(document.readyState)); // Log when DOMContentLoaded event occurs: window.addEventListener('DOMContentLoaded', () => console.log("DOM content loaded")); // Log when load event occurs: window.addEventListener('load', () => (console.log("All resources loaded))); // Output: // (1) loading // (2) interactive // (3) DOM content loaded // (4) complete // (5) All resources loaded
Page events
DOMContentLoaded
You can run some code only once the content of the DOM has loaded by listening out for the DOMContentLoaded
event on the global window
object.
This can be useful is you are trying to manipulate DOM elements and want to be sure they are fully parsed.
window.addEventListener('DOMContentLoaded', (event) => { alert("DOM ready!"); });
async
or defer
attribute block the loading of the DOM until they are complete. Thus, when the DOMContentLoaded
event is fired, you can be sure that scripts without these attributes have loaded. But non-blocking scripts with the async
or defer
attribute may or may not have loaded.
load
The load event on the window object is fired once the DOM and all resources, such as images and scripts, have loaded.
One example where waiting for loading
over DOMContentLoaded
makes sense is if you have a loading screen, and only want to reveal the full page to the user once everything is ready.
window.addEventListener('load', (event) => { alert("All resources loaded!"); });
beforeunload
The beforeunload
event on the window
object presents a chance to warn a user before leaving the page. It is triggered if a user tries to close the window, navigate to another page or refresh the page.
It only fires if a returnValue
is set for the event
parameter. But, ironically, most browsers override this message with a default message. In Chrome and Edge, the default message is "Leave Site? Changes you made may not be saved". A default message is used to prevent the user from being deceived to remain on the page.
Also note that in most browsers, the beforeunload event only fires if a user has interacted with the page. This is because it is primarily intended to warn users that unsaved changes may be lost.
window.addEventListener('beforeunload', (event) => { event.returnValue = `Leaving already?`; /* Note: this message is ignored by most browsers and a default message shown instead */ });
unload
The unload
event is fired when a user exits a page.
Understandably, browsers severely limit what can be done in response to this event.
But there is an important use that is not prevented by browsers: the navigator.sendBeacon
method, available on the window
object, which can be used to make a POST request to a same-origin API. This is typically used to save session data.
The unload event works by passing its function to the browser. The browser then executes this asynchronously when it can do so without blocking user navigation.
let sessionData = { data }; window.addEventListener("unload", function() { navigator.sendBeacon("/api", JSON.stringify(sessionData)); });
navigator.sendBeacon
on the unload
event is heavily dependent upon browser behavior. It is therefore a good idea not to rely upon this feature too heavily (e.g. best practice used as supplementary to intermediate POST requests during the session itself).
Summary
Sometimes we want some code to run only when a page has reached a certain state of loading (e.g. the DOM has loaded or all resources have loaded) or when a user is exiting the page.
We can listen out for these events by attaching event listeners to the global window
object:
Event | When? |
---|---|
DOMContentLoaded | The DOM has loaded |
loaded | All resources have loaded |
beforeunload | A user attempts to leave the page |
unload | A user is leaving the page |
Related links
- Google Web Dev on DEV Community (blog post): Sure you want to leave?—browser beforeunload event
- Mozilla MDN Web Docs: Navigator.sendBeacon()