jQuery Document Ready Equivalent in Vanilla JS
This article explains how to replicate jQuery's
$(document).ready() function using standard, modern Vanilla
JavaScript. In web development, ensuring that the Document Object Model
(DOM) is fully loaded before executing JavaScript is crucial for
preventing errors caused by trying to manipulate elements that do not
yet exist on the page. You will learn the direct event-based equivalent
in native JavaScript, the modern script loading approach that eliminates
the need for ready handlers entirely, and a fallback method for
asynchronous scripts.
The jQuery Pattern
In jQuery, code is typically wrapped in a ready block to wait for the DOM:
$(document).ready(function() {
// DOM is ready
});
// Or the shorthand syntax:
$(function() {
// DOM is ready
});The Native Equivalent:
DOMContentLoaded
The direct Vanilla JavaScript equivalent to
$(document).ready() is the DOMContentLoaded
event. It fires when the initial HTML document has been completely
parsed and loaded, without waiting for external stylesheets, images, and
subframes to finish loading.
document.addEventListener('DOMContentLoaded', () => {
// DOM is ready, your code goes here
});Modern Best Practice:
The defer Attribute
Modern web development often avoids DOM ready event listeners
entirely by using the defer attribute inside the
<script> tag. When using defer, the
browser downloads the script in parallel with parsing the HTML, but
executes it only after the HTML document is fully parsed, immediately
before DOMContentLoaded fires.
<head>
<script src="app.js" defer></script>
</head>When using defer, all code inside app.js
runs as if it were wrapped in a DOM ready handler:
// Inside app.js with defer enabled:
const element = document.querySelector('.my-class');
element.textContent = 'Updated content';Alternatively, placing a standard <script> tag at
the very bottom of the <body> element achieves a
similar effect, as all preceding DOM nodes are already parsed by the
time the script runs.
Handling Edge Cases with
readyState
If your script loads asynchronously (e.g., using async
or injected dynamically), the DOMContentLoaded event may
have already fired before your code executes. To handle this, check the
document.readyState property:
function ready(fn) {
if (document.readyState !== 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
// Usage
ready(() => {
// Code executes immediately if DOM is ready, or waits if still loading
});DOMContentLoaded
vs. window.onload
Be careful not to confuse DOMContentLoaded with the
load event (window.onload).
DOMContentLoaded(and jQuery's ready) triggers as soon as the HTML elements exist in memory.window.addEventListener('load', ...)waits for the entire page to finish loading, including large images, stylesheets, and embedded frames.