Vanilla JavaScript equivalent of jQuery’s $.ready() - how to call a function when the page/DOM is ready for it
With jQuery, we all know the wonderful .ready() function:
$('document').ready(function(){});
However, let’s say I want to run a function that is written in standard JavaScript with no library backing it, and that I want to launch a function as soon as the page is ready to handle it. What’s the proper way to approach this?
I know I can do:
window.onload="myFunction()";
Or I can use the body tag:
<body onload="myFunction()">
Or I can even try at the bottom of the page after everything, but the end body or html tag like:
<script type="text/javascript">
myFunction();
</script>
What is a cross-browser(old/new)-compliant method of issuing one or more functions in a manner like jQuery’s $.ready()?
The vanilla JavaScript equivalent of jQuery’s $.ready() is primarily the DOMContentLoaded event, which fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading. For cross-browser compatibility including older Internet Explorer versions, you’ll need to implement a more comprehensive solution that checks the document’s ready state and uses appropriate event listeners for different browsers.
Contents
- Modern Browser Solution
- Cross-Browser Implementation
- Alternative Approaches
- Browser Compatibility
- Recommended Solution
Modern Browser Solution
The most straightforward approach for modern browsers is to use the DOMContentLoaded event:
document.addEventListener("DOMContentLoaded", function() {
// Your code here
console.log("DOM is ready!");
});
This is the direct equivalent of jQuery’s $(document).ready() and works in all modern browsers including Chrome, Firefox, Safari, and IE9+ [source]. The event fires when the DOM is fully loaded but before images and other external resources have finished loading, making it faster than window.onload.
Cross-Browser Implementation
For full cross-browser compatibility including older versions of Internet Explorer, you need a more robust solution. Here’s a comprehensive implementation that handles all browsers from IE6 and up:
function docReady(fn) {
// Check if DOM is already available
if (document.readyState === "complete" || document.readyState === "interactive") {
// Call on next available tick
setTimeout(fn, 1);
} else {
// Use DOMContentLoaded for modern browsers
document.addEventListener("DOMContentLoaded", fn);
}
}
// Usage
docReady(function() {
// Your code here
console.log("DOM is ready!");
});
For even broader compatibility including IE8 and below, here’s an enhanced version:
function ready(fn) {
// Check if DOM is already loaded
if (document.readyState !== 'loading') {
fn();
} else if (document.addEventListener) {
// For modern browsers
document.addEventListener('DOMContentLoaded', fn);
} else {
// For IE8 and below
document.attachEvent('onreadystatechange', function() {
if (document.readyState === 'complete') {
fn();
}
});
}
}
// Usage
ready(function() {
// Your code here
console.log("DOM is ready!");
});
This implementation handles the different ways browsers signal that the DOM is ready, working across all major browsers including IE6+ [source]. According to Raymon Schouwenaar’s cross-browser solution, this approach covers all browser versions.
Alternative Approaches
Check Document Ready State Directly
You can check the document’s ready state without using events:
function domReady(callback) {
if (document.readyState === "interactive" || document.readyState === "complete") {
callback();
} else {
document.addEventListener("DOMContentLoaded", callback);
}
}
domReady(function() {
// Your code here
});
This method, as explained by Beeker.io, checks the current state and either executes immediately or waits for the event.
Script with Defer Attribute
Simply add the defer attribute to your script tag:
<script src="your-script.js" defer></script>
The defer attribute tells the browser to download the script without blocking HTML parsing and execute it after the document has been parsed but before DOMContentLoaded [source]. As mentioned in the Reddit discussion, this is a modern alternative to jQuery’s ready function.
Script at Bottom of Body
Place your script tag just before the closing </body> tag:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
</head>
<body>
<!-- Your content here -->
<script>
// Your code here
console.log("DOM is ready!");
</script>
</body>
</html>
This is the simplest approach and works reliably in all browsers, though it’s not as flexible as the event-based solutions [source].
Browser Compatibility
Here’s a compatibility overview for different approaches:
| Method | IE6-8 | IE9+ | Chrome | Firefox | Safari | Opera |
|---|---|---|---|---|---|---|
| DOMContentLoaded | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| onreadystatechange | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| document.readyState | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Script placement | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Defer attribute | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
The DOMContentLoaded event is supported by over 98% of browsers but not IE8 and below [source]. For complete compatibility, you need to combine multiple approaches as shown in the cross-browser implementation.
Recommended Solution
For most projects today, I recommend this cross-browser ready function:
function domReady(callback) {
// If DOM is already loaded, execute callback
if (document.readyState === 'interactive' || document.readyState === 'complete') {
callback();
} else {
// For modern browsers
document.addEventListener('DOMContentLoaded', callback);
// For IE8 and below
if (document.attachEvent) {
document.attachEvent('onreadystatechange', function() {
if (document.readyState === 'complete') {
callback();
}
});
}
}
}
// Usage
domReady(function() {
// Multiple functions can be added
initializeComponents();
setupEventListeners();
loadDynamicContent();
});
// Or create a namespace for multiple functions
var DOMReady = {
callbacks: [],
add: function(callback) {
if (document.readyState === 'interactive' || document.readyState === 'complete') {
callback();
} else {
this.callbacks.push(callback);
}
},
ready: function() {
var callbacks = this.callbacks;
for (var i = 0; i < callbacks.length; i++) {
callbacks[i]();
}
}
};
// Add your functions
DOMReady.add(function() {
console.log("First function ready");
});
DOMReady.add(function() {
console.log("Second function ready");
});
// Initialize when DOM is ready
domReady(DOMReady.ready);
This solution provides:
- Full cross-browser compatibility (IE6+)
- Support for multiple callback functions
- Immediate execution if DOM is already ready
- Clean, reusable code structure
According to the CSS-Tricks article, this approach works effectively across all browsers while maintaining clean, dependency-free code.
Sources
- Stack Overflow - Vanilla JavaScript equivalent of jQuery’s $.ready()
- GitHub - vanilla-ready
- Reddit - What should I use instead of jQuery’s $(document).ready()?
- Stack Overflow - What is the non-jQuery equivalent of ‘$(document).ready()’?
- Raymon Schouwenaar - Cross-browser Document Ready with Vanilla JavaScript
- Beeker.io - jQuery $(document).ready() Equivalent in Vanilla JavaScript
- CSS-Tricks - Cross-Browser Dependency-Free DOM Ready
- Wikitechy - $(document).ready equivalent without jQuery
- WPShout - jQuery document.ready in Vanilla JavaScript
- SitePoint - Replace the jQuery Document Ready Function with JavaScript
Conclusion
The vanilla JavaScript equivalent of jQuery’s $.ready() can be implemented using several approaches depending on your browser compatibility requirements:
- For modern browsers: Use
document.addEventListener("DOMContentLoaded", callback)- this is the cleanest and most straightforward solution - For full cross-browser compatibility: Implement a function that checks
document.readyStateand uses bothaddEventListenerandattachEventfor older IE versions - For simplicity: Place scripts at the end of the body or use the
deferattribute - For multiple functions: Create a ready function that maintains an array of callbacks
The recommended approach combines modern event handling with legacy support, ensuring your code works across all browsers from IE6 to the latest versions. This solution maintains the same behavior as jQuery’s ready function while being lightweight and dependency-free.
Remember that while window.onload works, it waits for all resources (images, stylesheets, etc.) to load, whereas DOM-ready fires as soon as the HTML structure is available, making it faster and more similar to jQuery’s behavior.