DOMContentLoaded
When a browser loads an HTML page, it constructs the Document Object Model (DOM) tree based on the HTML structure. The DOMContentLoaded
event is triggered when the initial HTML document has been completely loaded and parsed, and the DOM tree is built. However, this event fires before all external resources like images and stylesheets are fully loaded.
Why is it important?
- It allows JavaScript code to run as soon as the DOM is ready, even if external resources are still loading.
- Useful for initializing user interface elements or performing tasks that don't depend on external resources.
Example:
<script>
function ready() {
alert('DOM is ready');
}
document.addEventListener('DOMContentLoaded', ready);
</script>
In this example, the ready
function is executed as soon as the DOMContentLoaded event is fired, indicating that the DOM is ready.
Note:
Scripts in the HTML document can delay the DOMContentLoaded event if they need to execute before the DOM is fully constructed.
Scripts and DOMContentLoaded
Scripts in an HTML document can affect the timing of the DOMContentLoaded
event. When the browser encounters a <script>
tag while parsing the HTML document, it typically pauses parsing and executes the script before continuing to build the DOM. This is done to ensure that scripts can manipulate the DOM if needed.
How does this affect DOMContentLoaded?
- If a
<script>
tag is encountered before the closing</body>
tag, the browser must execute it before the DOMContentLoaded event fires. - Scripts that modify the DOM or use
document.write()
may cause delays in DOMContentLoaded.
Example:
<script>
document.addEventListener('DOMContentLoaded', () => {
alert('DOM ready!');
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.3.0/lodash.js"></script>
<script>
alert('Library loaded, inline script executed');
</script>
In this example, the alert "DOM ready!" is shown after all scripts are executed, indicating that DOMContentLoaded waits for all scripts to execute.
Styles and DOMContentLoaded
While external style sheets (<link>
tags) don't affect the construction of the DOM tree, they can still influence the timing of the DOMContentLoaded
event when combined with scripts.
How does this work?
- DOMContentLoaded doesn't wait for external stylesheets to load.
- However, if a script requires information about the styles applied to elements (e.g., dimensions or positions), it must wait for styles to be loaded.
- Therefore, if a script follows a stylesheet in the document, DOMContentLoaded will wait for the stylesheet to load before executing the script.
Example:
<link type="text/css" rel="stylesheet" href="style.css" />
<script>
// The script waits until the stylesheet is loaded to access style-dependent properties
alert(getComputedStyle(document.body).marginTop);
</script>
In this example, the script waits for the stylesheet to load before accessing the computed style of document.body
.
Note:
Scripts with the async
attribute or dynamically generated scripts added to the document do not block DOMContentLoaded.
Browser Autofill and DOMContentLoaded
Modern browsers like Firefox, Chrome, and Opera often have autofill features for forms. When a user revisits a page with a form they previously filled out, the browser may attempt to autofill the form fields.
How does this relate to DOMContentLoaded?
- Browser autofill typically occurs during the DOMContentLoaded event.
- If the DOMContentLoaded event is delayed due to long-loading scripts, autofill may also be delayed until the event fires.
Example:
- Suppose a webpage has a form with login and password fields, and the browser remembers the values for autofill.
- When the DOMContentLoaded event is triggered, the browser may try to autofill the form fields if the user has permitted autofill.
Note:
- Delaying DOMContentLoaded due to long-loading scripts can also delay autofill, leading to a delay in autofill behavior on the webpage.
window.onload
After the DOMContentLoaded
event fires, the browser continues to load external resources such as images and stylesheets. The window.onload
event is triggered when all these resources, including images, styles, and scripts, are fully loaded.
What happens during window.onload
?
- The
window.onload
event handler is called when all resources on the page, including images and stylesheets, have finished loading. - This event is useful for tasks that depend on all resources being available, such as accessing the dimensions of images.
Example:
<script>
window.onload = function() {
alert('Page loaded');
alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`);
};
</script>
<img id="img" src="https://en.js.cx/clipart/train.gif?speed=1&cache=0">
In this example, the window.onload
event handler is triggered after the image has finished loading, allowing access to its dimensions.
Note:
Unlike DOMContentLoaded, window.onload
waits for all resources to be loaded, including images and stylesheets.
This event is suitable for tasks that require all resources to be available.
window.onunload
The window.onunload
event is triggered when a user navigates away from a webpage or closes the browser window. This event provides an opportunity to perform tasks before the user leaves the page completely.
What happens during window.onunload
?
- The
window.onunload
event handler is executed when the user is about to leave the page. - It can be used to perform tasks such as closing related popup windows or sending analytics data to a server.
Example:
let analyticsData = {
/* object with gathered data */
};
window.addEventListener('unload', function () {
navigator.sendBeacon('/analytics', JSON.stringify(analyticsData));
});
In this example, the unload
event is used to send analytics data to the server using navigator.sendBeacon()
, ensuring that the data is sent even if the user navigates away from the page.
Note:
navigator.sendBeacon()
is a method that allows sending data to a server in the background, even after the user navigates away from the page.
It's commonly used for sending analytics data or other information that should be recorded before the user leaves the page.
window.onbeforeunload
The window.onbeforeunload
event is triggered when a user attempts to leave a webpage by navigating to a different URL or closing the browser window. It provides a mechanism to prompt the user for confirmation before they leave the page.
What happens during window.onbeforeunload
?
- The
window.onbeforeunload
event handler is executed when the user initiates navigation away from the page or tries to close the window. - It can be used to display a confirmation dialog asking the user if they are sure they want to leave the page.
Example:
window.onbeforeunload = function () {
return 'There are unsaved changes. Leave now?';
};
In this example, the onbeforeunload
event handler returns a string message indicating that there are unsaved changes, prompting the browser to display a confirmation dialog to the user.
Note:
Returning a non-empty string from the onbeforeunload
event handler triggers a confirmation dialog in most modern browsers, asking the user if they are sure they want to leave the page.
This event can be used to prevent accidental navigation away from a page or closing the browser window without saving changes.
Differences Between unload
and beforeunload
Events:
Although both unload
and beforeunload
events are triggered when a user navigates away from a webpage or closes the browser window, there are significant differences between them in terms of their behavior and usage.
1. Timing:
- The
unload
event occurs after the user has initiated navigation away from the page or closed the window. It indicates that the page is being unloaded. - The
beforeunload
event occurs before the user actually leaves the page or closes the window. It provides an opportunity to prompt the user for confirmation before they leave.
2. Actions:
- The
unload
event is typically used for performing tasks that don't require user interaction and can be executed before the page is fully unloaded, such as closing related popup windows or sending analytics data. - The
beforeunload
event is used to prompt the user for confirmation before they leave the page. It's commonly used to prevent accidental navigation away from a page without saving changes.
Example:
- Use
unload
event for tasks like closing related popup windows or sending analytics data. - Use
beforeunload
event to display a confirmation dialog asking the user if they are sure they want to leave the page without saving changes.
Note:
- Both events can be used to perform tasks before the user leaves the page, but they serve different purposes and have different timing.
document.readyState Property
The document.readyState
property provides information about the current state of the document's loading process. It indicates whether the document is still loading, has been fully read, or if all resources such as images and stylesheets have been loaded.
Possible Values:
"loading"
: Indicates that the document is still loading."interactive"
: Indicates that the document has been fully read."complete"
: Indicates that the document has been fully read and all external resources (e.g., images, stylesheets) are loaded.
How to Use:
You can check the value of document.readyState
to determine if the document is fully loaded. If the value is "loading"
, the document is still loading, and you may need to wait for the DOMContentLoaded
event. If the value is "complete"
, the document and all external resources are fully loaded.
Example:
function work() {
/*...*/
}
if (document.readyState == 'loading') {
// Document is still loading, wait for the DOMContentLoaded event
document.addEventListener('DOMContentLoaded', work);
} else {
// Document is already fully loaded
work();
}
In this example, the work()
function is executed either immediately if the document is already fully loaded, or it is attached as a listener for the DOMContentLoaded
event if the document is still loading.
Note:
The readystatechange
event can also be used to track changes in the document's loading state, but it is less commonly used nowadays.
Full Events Flow:
Understanding the full events flow of a webpage loading process involves tracking the sequence of events triggered during different stages of loading, including the DOMContentLoaded
, window.onload
, and various resource loading events.
Example:
<script>
log('initial readyState:' + document.readyState);
document.addEventListener('readystatechange', () =>
log('readyState:' + document.readyState)
);
document.addEventListener('DOMContentLoaded', () => log('DOMContentLoaded'));
window.onload = () => log('window onload');
</script>
<iframe src="iframe.html" onload="log('iframe onload')"></iframe>
<img src="https://en.js.cx/clipart/train.gif" id="img" />
<script>
img.onload = () => log('img onload');
</script>
Events Flow:
- The initial readyState is logged.
- The
readystatechange
event is logged whenever the readyState changes. - The
DOMContentLoaded
event is logged when the initial HTML document is fully parsed and the DOM is built. - The
iframe
element loads its content, triggering theonload
event. - The
img
element starts loading its image. When the image is fully loaded, theonload
event is triggered. - The readyState changes to "complete", indicating that the document and all resources are fully loaded.
- The
window.onload
event is triggered, indicating that the entire page, including all resources, is fully loaded.
Note:
- The order of events may vary depending on factors such as network speed and resource loading times.
- Understanding the events flow helps in optimizing webpage performance and ensuring that scripts and styles are applied at the appropriate time.
This concludes the overview of the full events flow during the webpage loading process.
In modern websites, the loading and execution of scripts play a crucial role in webpage performance and user experience. The way scripts are handled by the browser can impact the rendering of content and user interactions. Let's explore the concepts of async
and defer
attributes in script tags, and how they affect the loading behavior of scripts.
1. Script Loading Issues:
When a browser encounters a <script>
tag in the HTML document, it typically pauses parsing and executes the script immediately. This behavior can lead to two significant issues:
-
Blocking Page Rendering: Scripts can block the rendering of page content, especially if they are large or take a long time to execute. This delays the display of content to users.
-
Script Dependency: Scripts cannot see DOM elements below them in the HTML document, which limits their ability to interact with or manipulate those elements.
2. Solutions: async
and defer
Attributes:
To address these issues, HTML introduced two attributes for <script>
tags: async
and defer
.
defer
Attribute:
The defer
attribute tells the browser not to wait for the script. Instead, it allows the browser to continue parsing and building the DOM while the script loads in the background.
The script with defer
attribute will execute only after the DOM is fully built, but before the DOMContentLoaded event.
Example:
<script `defer` src="script.js"></script>
async
Attribute:
The async
attribute, like defer
, makes the script non-blocking. However, it has some key differences:
Scripts with async
are completely independent, meaning they do not block other scripts, and other scripts do not wait for them.
DOMContentLoaded and other scripts do not wait for async
scripts to load or execute.
Example:
<script `async` src="script.js"></script>
3. Differences Between async
and defer
:
Blocking Behavior: Scripts with defer
do not block page rendering, but they wait for the DOM to be fully built. On the other hand, scripts with async
do not block page rendering and are executed independently.
Execution Order: Scripts with defer
maintain their relative order and execute after the DOM is fully built. In contrast, scripts with async
are executed as soon as they are loaded, regardless of their order in the document.
4. Dynamic Scripts:
Another way to add scripts to a webpage is dynamically using JavaScript. Dynamic scripts behave similarly to scripts with async
, as they do not block rendering and execute independently.
By default, dynamic scripts are async
hronous, but you can explicitly set async
to false to make them behave like defer
red scripts, ensuring they execute in the document order.
Example:
let script = document.createElement('script');
script.src = "script.js";
document.body.appendChild(script);
Conclusion:
Understanding the behavior of script loading attributes async
and defer
is crucial for optimizing webpage performance and user experience. By using these attributes appropriately, you can ensure that scripts do not block page rendering and execute efficiently, leading to faster and smoother user interactions.