To ensure JavaScript executes after the page fully loads (including HTML, CSS, images, and other resources), you need to delay execution until the browser signals that the page is ready. Below are detailed methods with examples:
1. Use window.onload (Classic Method)
The window.onload event fires when the entire page (including external resources) is fully loaded.
window.onload = function() {
  // Code here runs after the page is fully loaded
  console.log("Page fully loaded (including images)");
};Pros:
- Guarantees all resources (images, stylesheets) are loaded.
- Simple syntax for single functions.
Cons:
- Overwrites previous onloadhandlers if assigned multiple times.
2. Use DOMContentLoaded (Faster Execution)
The DOMContentLoaded event fires when the HTML is parsed and the DOM is ready, without waiting for images/stylesheets.
document.addEventListener("DOMContentLoaded", function() {
  // Code here runs after the DOM is ready
  console.log("DOM fully parsed (no external resources)");
});Pros:
- Faster execution (no wait for images/stylesheets).
- Allows multiple event listeners.
Cons:
- Scripts requiring images/stylesheets may fail.
3. Place Scripts at the End of <body>
Place your <script> tag just before the closing </body> tag to ensure the DOM is parsed before execution.
<body>
  <!-- Page content -->
  <script>
    // Code here runs after the DOM is parsed
    console.log("DOM ready (script at end of body)");
  </script>
</body>Pros:
- No need for event listeners.
- Works in all browsers.
Cons:
- Not suitable for scripts in the <head>.
4. Use the defer Attribute
The defer attribute delays script execution until after HTML parsing, while preserving execution order.
<head>
  <script src="script.js" defer></script>
</head>Pros:
- Non-blocking (allows HTML parsing to continue).
- Maintains script order.
Cons:
- Only works for external scripts (not inline scripts).
5. Modern Approach with async/await (Dynamic Imports)
Dynamically import scripts after the page loads.
window.addEventListener("load", async function() {
  const module = await import('./module.js');
  module.runCode();
});Pros:
- Useful for modular code.
- Non-blocking and efficient.
Cons:
- Requires modern browsers.
6. jQuery’s $(document).ready()
For jQuery users, this fires when the DOM is ready (similar to DOMContentLoaded).
$(document).ready(function() {
  console.log("DOM ready (jQuery)");
});Shorthand:
$(function() {
  console.log("DOM ready (jQuery shorthand)");
});Key Scenarios & Recommendations
| Scenario | Recommended Method | 
|---|---|
| Wait for all resources | window.onload | 
| Fast DOM interaction | DOMContentLoadedor<script defer> | 
| Legacy code | <script>at end of<body> | 
| Modular/Modern code | async/awaitwith dynamic imports | 
Full Example: Combining Events
// Run code when DOM is ready
document.addEventListener("DOMContentLoaded", function() {
  console.log("DOM ready");
});
// Run code when page fully loads (including images)
window.addEventListener("load", function() {
  console.log("Page fully loaded");
});
// Fallback for older browsers
window.onload = function() {
  console.log("Fallback for window.onload");
};Common Pitfalls
- Blocking Rendering:
 Avoid placing scripts in<head>withoutdefer/async.
- Multiple window.onloadHandlers:
 UseaddEventListenerinstead ofonloadto avoid overwriting.
- External Resource Dependence:
 Usewindow.onloadif your code relies on images/stylesheets.
Summary
- DOM Ready: Use DOMContentLoadedor place scripts at the end of<body>.
- Full Load: Use window.onload.
- Modern Apps: Use deferor dynamic imports withasync/await.
- jQuery: Use $(document).ready()for legacy codebases.