Why you should abandon jQuery for $(document).ready in 2025?
\nIf you're still writing $(document).ready(function() { ... }) — you're either working on a legacy project or missing out on the capabilities of modern JavaScript. In 2025, jQuery is like a feature phone: it works, but everyone has long since switched to touchscreens.
On Stack Overflow, the question $(document).ready equivalent without jQuery has gathered hundreds of thousands of views. This means developers worldwide are looking for lightweight, fast, and modern ways to execute code after the DOM is loaded. And the answer is simple: native browser support has long covered 100% of the needs that jQuery once solved.
In this article, we'll cover 3 best ways to replace $(document).ready with pure JavaScript, discuss performance nuances, and show real code examples you can use today.
DOMContentLoaded — the main hero without jQuery
\nThe most direct equivalent of $(document).ready is the DOMContentLoaded event. It fires when the browser has fully loaded and parsed the HTML document, but before images, styles, and other resources. This is exactly what jQuery did under the hood.
Here's the basic syntax:
\ndocument.addEventListener('DOMContentLoaded', function() {\n // Your code will execute after the DOM is fully loaded\n console.log('DOM fully loaded and ready!');\n document.querySelector('.header').style.color = '#2c3e50';\n});\nWhy is this better than jQuery?
\n- \n
- Speed: No need to load 30+ KB of library for a single function. \n
- Control: You know exactly what happens at load time. \n
- Compatibility: Works in all modern browsers (IE9+, Chrome, Firefox, Safari, Edge). \n
But there's a nuance: if your script is loaded after the DOM is ready, the event won't fire. The solution is to check document.readyState:
function ready(fn) {\n if (document.readyState !== 'loading') {\n fn(); // DOM is already loaded\n } else {\n document.addEventListener('DOMContentLoaded', fn);\n }\n}\nready(function() {\n console.log('Guaranteed to execute after DOM is loaded');\n});\nThis pattern is the gold standard for replacing $(document).ready in 2025.
The defer attribute: the simplest way without a single line of code
\nWhat if I told you that you don't need to write DOMContentLoaded at all? The defer attribute in the <script> tag does all the work for you:
<script src="script.js" defer></script>\nHow does it work? The browser loads the script in parallel with the HTML, but executes it only after the document is fully parsed. This is equivalent to having all the code inside script.js automatically wrapped in $(document).ready.
Pros:
\n- \n
- Zero extra code — just add the attribute. \n
- Scripts with
deferexecute in the order they appear in the HTML. \n - Works in 97% of browsers (including older versions of Safari). \n
When to use? Ideal for regular scripts that need to work with the DOM but don't block rendering. For example:
\n<script src="analytics.js" defer></script>\n<script src="app.js" defer></script>\n<!-- app.js will execute after analytics.js, but before window.onload -->\nCompare with jQuery: $(document).ready inside app.js is extra code. With defer, you simply write:
// app.js — no