Eventos de carga de página JavaScript (DOMContentLoaded vs load)

Entender la diferencia entre DOMContentLoaded y load es clave para ejecutar código en el instante correcto, evitar errores y mejorar el rendimiento. A través de ejemplos prácticos, se aprende cuándo manipular el DOM, inicializar componentes o esperar a que todo el contenido esté completamente cargado.

eventos de carga en javasript domcontentload vs load

1. ¿Qué es el evento de carga de página en JavaScript?

El evento de carga de página hace referencia a momentos específicos del proceso en el que el navegador termina de cargar el documento HTML y/o sus recursos, y JavaScript puede ejecutar código con la seguridad de que ciertos elementos ya existen en el DOM.

👉 En términos simples:
Sirve para ejecutar JavaScript en el momento correcto, evitando errores por intentar acceder a elementos que todavía no fueron cargados.

1.1. ¿Por qué ocurre la carga de página?

Cuando el navegador recibe un archivo HTML:

  1. Lee la estructura HTML de arriba hacia abajo.
  2. Construye el DOM (Document Object Model).
  3. Descarga recursos externos (CSS, imágenes, scripts).
  4. Dispara eventos de carga (que iremos viendo) cuando determinadas fases se completan.

JavaScript necesita saber cuándo puede:

  • Buscar elementos (querySelector)
  • Modificar el DOM
  • Inicializar componentes
  • Ejecutar lógica dependiente de la interfaz

2. Ciclo de vida de una página HTML

Antes de profundizar en el funcionamiento de DOMContentLoaded y load, es importante conocer el ciclo de vida de una página web.

El ciclo de vida de una página HTML es el proceso completo que sigue el navegador desde que recibe el HTML hasta que la página se muestra e interactúa con JavaScript.

Este ciclo se puede dividir en fases bien definidas, y cada una impacta directamente en cuándo y cómo se ejecuta tu código JS:

2.1. Recepción del HTML

El navegador:

  • Solicita el archivo HTML al servidor
  • Recibe el texto HTML

Todavía:
❌ No hay DOM
❌ No se puede acceder a elementos

2.2. Parseo del HTML (lectura del documento)

El navegador comienza a leer el HTML de arriba hacia abajo.

<!DOCTYPE html>
<html>
  <head>
    <title>Mi página</title>
  </head>
  <body>
    <h1 id="titulo">Hola</h1>
  </body>
</html>Lenguaje del código: HTML, XML (xml)

¿Qué significa “parsear”?

  • Interpretar etiquetas
  • Validar estructura
  • Preparar nodos del documento

En este punto:

  • El navegador va entendiendo el HTML
  • Todavía no existe el DOM completo

2.3. Construcción del DOM (Document Object Model)

Mientras parsea el HTML, el navegador crea una estructura en forma de árbol:

document
 └── html
     ├── head
     └── body
         └── h1
Lenguaje del código: JavaScript (javascript)

Cada etiqueta se convierte en un nodo del DOM.

Ejemplo en JavaScript

console.log(document.body);
Lenguaje del código: JavaScript (javascript)

✔️ Esto solo funciona cuando el DOM ya existe.

2.4. Encuentro de scripts durante el parseo:

Aclaración!…. Durante el parseo, el navegador puede encontrar script dentro sin atributos y con atributos, y el comportamiento que seguirá dicho parseo dependerá de esta situación:

Caso A: <script> normal (Sin ningun atributo)

<script src="app.js"></script>Lenguaje del código: HTML, XML (xml)

📌 Cuando el navegador encuentra este script:

  1. Detiene el parseo del HTML
  2. Descarga el JS
  3. Ejecuta el JS
  4. Continúa con el HTML

⚠️ Problema típico:

document.querySelector('#titulo').textContent = 'Nuevo texto';Lenguaje del código: JavaScript (javascript)

Si el elemento aún no fue parseado:
null

Caso B: <script defer> (Con atributo defer)

<script src="app.js" defer></script>Lenguaje del código: HTML, XML (xml)

✔️ Comportamiento:

  • El HTML sigue parseándose
  • El script se ejecuta cuando el DOM está completo

👉 Equivale conceptualmente a DOMContentLoaded.

Caso C: <script async> (Con atributo)

<script src="app.js" async></script>Lenguaje del código: HTML, XML (xml)

✔️ Comportamiento:

  • Se descarga en paralelo
  • Se ejecuta cuando termina de descargarse
  • Puede ejecutarse antes o después del DOM

⚠️ No es seguro para manipular DOM sin control.

2.5. DOM completamente construido

En este momento:

  • Todo el HTML ya fue parseado
  • El árbol DOM está listo
  • Se dispara DOMContentLoaded
document.addEventListener('DOMContentLoaded', () => {
  console.log('DOM listo');
});Lenguaje del código: JavaScript (javascript)

✔️ Ya podés:

  • Buscar elementos
  • Agregar eventos
  • Modificar el DOM

2.6. Carga de recursos externos

Mientras tanto, el navegador carga:

  • Imágenes
  • CSS
  • Fuentes
  • Videos
  • Iframes

Ejemplo:

<img src="foto.jpg">Lenguaje del código: HTML, XML (xml)

La imagen puede tardar más que el HTML.

2.7. Página completamente cargada

Cuando:

  • DOM ✔️
  • Imágenes ✔️
  • CSS ✔️
  • Recursos ✔️

👉 Se dispara el evento load.

window.addEventListener('load', () => {
  console.log('Página totalmente cargada');
});Lenguaje del código: JavaScript (javascript)

✔️ Ideal para:

  • Medir tamaños reales
  • Trabajar con imágenes
  • Animaciones dependientes de recursos

2.8. Renderizado y pintura en pantalla

El navegador:

  • Aplica CSS
  • Calcula layouts
  • Pinta los píxeles
  • Permite interacción del usuario

Este proceso ocurre en paralelo al JS.

2.9. Línea de tiempo resumida

HTML recibido
↓
Parseo HTML
↓
Construcción del DOM
↓
DOMContentLoaded
↓
Carga de recursos
↓
load
↓
Página visible e interactiva

3. ¿Qué es el evento DOMContentLoaded?

DOMContentLoaded es un evento del objeto document que el navegador dispara automáticamente cuando:

✔️ Todo el HTML fue parseado
✔️ El DOM está completamente construido

NO espera a que se carguen:

  • Imágenes
  • Videos
  • CSS externos
  • Fuentes
  • Iframes

👉 En otras palabras:
el DOM ya existe y puede manipularse con seguridad.

¿En qué momento exacto se ejecuta?

Ocurre justo después de que el navegador termina de construir el árbol DOM.

📌 Línea de tiempo simplificada:

HTML parseado
↓
DOM construido
↓
DOMContentLoaded  ← AQUÍ
↓
Carga de imágenes y recursos
↓
load

¿Qué partes de la página ya están disponibles?

Cuando se dispara DOMContentLoaded, ya podés acceder a:

✔️ Todos los elementos HTML (div, form, button, etc.)
✔️ Atributos (id, class, data-*)
✔️ Estructura del DOM completa
✔️ Eventos (click, submit, etc.)

❌ Todavía no es seguro:

  • Medir tamaños reales de imágenes
  • Trabajar con recursos pesados.

3.1. Ejemplo usando DOMContentLoaded.

Para entender mejor el funcionamiento de este evento lo explicaremos con este ejemplo:

3.1.1. El Escenario (HTML)

Supongamos que dentro de nuestro archivo HTML tenemos un botón. Queremos que, cuando el usuario haga clic en él, se muestre un mensaje de alerta.

<button id="miBoton">¡Haz clic aquí!</button>Lenguaje del código: HTML, XML (xml)

3.1.2. El Objetivo

Para lograr esto de una forma correcta, debemos asegurarnos de que el navegador (como Google Chrome) al cargar dicho archivo HTML, primero haya parseado o leído todo el documento y construido la estructura de la página. Recién después de eso, debe ejecutar el JavaScript que realiza la acción de dicho botón.

3.1.3. La Solución (JavaScript con DOMContentLoaded )

Para lograr esta sincronización perfecta, en nuestro archivo JavaScript utilizaremos el evento DOMContentLoaded de la siguiente manera:

// Usamos el objeto 'document' porque es el dueño de la estructura HTML
document.addEventListener('DOMContentLoaded', () => {
    
    // Ahora que el DOM está listo, buscamos el botón por su ID
    const btn = document.getElementById('miBoton');

    // Le asignamos la función de mostrar el mensaje al hacer clic
    btn.addEventListener('click', () => {
        alert("¡Acción ejecutada con éxito!");
    });

    console.log("El JavaScript se vinculó al botón después de leer el HTML.");
});Lenguaje del código: JavaScript (javascript)

3.1.4. ¿Cuales son las ventajas de usar DOMContentLoaded aquí?

La funcionalidad de este evento es vital por las siguientes razones:

Garantía de Lectura
Al utilizar este evento, nos aseguramos de que el navegador haya cargado y procesado completamente el HTML, incluyendo elementos clave como botones, formularios o contenedores que luego serán manipulados con JavaScript.
Ejecución Segura
Garantiza que el código JavaScript se ejecute en el momento correcto. Sin DOMContentLoaded, el script podría ejecutarse antes de que el navegador haya leído ciertos elementos del HTML.
Prevención de Errores
Evita que JavaScript intente acceder a elementos que todavía no existen en el DOM, lo que podría provocar errores como Uncaught TypeError: Cannot read properties of null y romper la aplicación.

3.1.5. Conclusión:

Esta es la función principal de este evento: actuar como un semáforo. Le dice a nuestro código: «Espera, todavía no arranques; deja que Google termine de construir la página, y en cuanto el último elemento HTML esté listo, yo te aviso para que puedas trabajar sin errores».

4. ¿Qué es el evento load del objeto window?

El evento load es un evento del objeto global window que el navegador dispara automáticamente cuando la página está completamente cargada.

👉 “Completamente cargada” significa:

✔️ HTML parseado
✔️ DOM construido
✔️ CSS cargado
✔️ Imágenes cargadas
✔️ Fuentes cargadas
✔️ Iframes y otros recursos externos cargados

Es decir: TODO terminó de cargarse.

¿En qué momento exacto se ejecuta?

Ocurre al final del ciclo de carga de la página.

📌 Línea de tiempo clara:

HTML recibido
↓
Parseo HTML
↓
DOM construido
↓
DOMContentLoaded
↓
Carga de imágenes / CSS / recursos
↓
load  ← AQUÍ

load siempre se ejecuta después de DOMContentLoaded.

4.1. Ejemplo usando el evento load

4.1.1. El Escenario (HTML)

Supongamos que tenemos un HTML donde queremos mostrar una pantalla de carga (spinner) que cubra toda la página y que solo desaparezca cuando absolutamente todo (incluyendo fotos pesadas y estilos CSS) se haya descargado correctamente.

<div id="loader">Cargando sitio completo...</div>
<img id="bannerCaro" src="imagen-pesada-4k.jpg" alt="Banner Principal">
<p>Bienvenidos a mi sitio web.</p>Lenguaje del código: HTML, XML (xml)

4.1.2. El Objetivo

Para lograr esto, necesitamos asegurarnos de que el navegador no solo haya leído el HTML, sino que también haya terminado de descargar los archivos externos. Si quitamos el mensaje de «Cargando…» antes de que la imagen pesada baje, el usuario verá un hueco blanco o una página «rota» que se va armando de a poco.

4.1.3. La Solución (Usamoa evento load)

Para lograr que el mensaje desaparezca solo cuando la página esté 100% lista, usaremos el evento load en nuestro archivo JavaScript:

JavaScript

// Usamos el objeto 'window' porque este evento abarca toda la ventana y sus recursos
window.addEventListener('load', () => {
    
    console.log("--- ESTADO: TODO CARGADO ---");
    console.log("El HTML, las imágenes y el CSS están listos.");

    // Buscamos el div del cargador y lo ocultamos
    const loader = document.getElementById('loader');
    loader.style.display = 'none';

    // Ahora podemos medir dimensiones reales de la imagen si quisiéramos
    const imagen = document.getElementById('bannerCaro');
    console.log("La imagen mide exactamente: " + imagen.offsetWidth + "px");
});
Lenguaje del código: JavaScript (javascript)

4.1.4. ¿Cuales son las ventajas de usar load aquí?

La funcionalidad de este evento es específica para recursos externos:

Garantía de Recursos
A diferencia de DOMContentLoaded, el evento load espera a que todos los recursos estén completamente cargados, incluyendo imágenes, videos, fuentes y hojas de estilo.
Cálculos Precisos
Permite obtener medidas reales de los elementos visuales. Si intentás calcular el ancho o alto de una imagen antes de este evento, JavaScript podría devolver 0px porque el recurso aún no se descargó.
Finalización de Experiencia
Es ideal para indicar que el sitio ya está listo en su forma visual definitiva, por ejemplo, ocultando un loader o mostrando un mensaje de “carga completa” al usuario.

4.1.5. Comparativa: ¿Cuándo usar DOMContentLoaded y cuándo load?

Es fundamental saber elegir la herramienta correcta según lo que necesitemos hacer:

SituaciónEvento Ideal¿Por qué?
Hacer que un botón funcione (clic)DOMContentLoadedEs mejor porque es más rápido. El usuario puede interactuar con el botón aunque las fotos del fondo sigan cargando.
Quitar un «Spinner» de cargaloadEs mejor porque asegura que el usuario no vea la página «a medio terminar». Queremos que vea el diseño final.
Validar un formulario de textoDOMContentLoadedNo necesitamos esperar a que cargue el logo de la empresa para validar un email.
Animaciones que dependen del tamaño de fotosloadSi la animación necesita saber dónde termina una foto, la foto debe estar cargada al 100%.

Conclusión: Usamos DOMContentLoaded para la interacción (que la página «haga algo») y usamos load para la visualización (que la página «se vea perfecta»).

4.1.6. Casos de uso reales del evento load

✔️ Medir tamaños reales
✔️ Trabajar con imágenes
✔️ Iniciar animaciones complejas
✔️ Calcular layouts finales
✔️ Mostrar la página cuando todo esté listo

4.1.7. ¿Cuándo NO conviene usar load?

❌ Para botones, formularios, menús
❌ Para inicializar eventos del DOM
❌ Cuando buscás rapidez

En esos casos:
👉 DOMContentLoaded o defer

4.1.8. Error común

❌ Usar load para todo

window.addEventListener('load', initApp);Lenguaje del código: JavaScript (javascript)

⚠️ Hace que la app arranque más tarde de lo necesario.

5. ¿Qué son los atributos defer y async?

defer y async son atributos booleanos del elemento <script> en HTML.

Sirven para controlar cuándo y cómo se descargan y ejecutan los scripts JavaScript durante la carga de la página.

No pertenecen a JavaScript:

  • Son HTML
  • Los interpreta el navegador

✔️ EJEMPLO sin usar estos atributos:

<script src="app.js"></script>Lenguaje del código: HTML, XML (xml)

Comportamiento:

  1. El navegador está parseando el HTML
  2. Encuentra el <script>
  3. Se detiene el parseo
  4. Descarga el JS
  5. Ejecuta el JS
  6. Continúa con el HTML

❌ Problemas:

  • Bloquea el render
  • El DOM puede no estar completo
  • Posibles errores al acceder al DOM

5.1. Atributo defer

defer indica al navegador:

👉 “Descargá este script en paralelo, pero ejecutalo cuando el DOM esté completamente construido”.

5.1.1. Ejemplo con defer

<script src="app.js" defer></script>Lenguaje del código: HTML, XML (xml)

¿Qué hace el navegador?

  1. Parseo del HTML continúa
  2. Descarga app.js en segundo plano
  3. Construye el DOM
  4. Ejecuta el script
  5. Luego dispara DOMContentLoaded

📌 Importante:

  • Los scripts defer respetan el orden
  • Se ejecutan antes de DOMContentLoaded

5.2. Atributo async

async indica:

👉 “Descargá este script en paralelo y ejecutalo apenas termine de descargarse”.

5.2.1. Ejemplo con async

<script src="analytics.js" async></script>Lenguaje del código: HTML, XML (xml)

Comportamiento real:

  • Se descarga en paralelo
  • Se ejecuta en cualquier momento
  • Puede interrumpir el parseo del HTML

⚠️ No espera:

  • DOM
  • Otros scripts
  • Orden

5.2.2. ¿Cuándo usar async entonces?

✔️ Scripts independientes
✔️ Analytics
✔️ Publicidad
✔️ Tracking
✔️ Widgets externos

Ejemplo típico:

<script src="https://analytics.com/script.js" async></script>Lenguaje del código: HTML, XML (xml)

5.3. ¿Cómo usar defer y async correctamente?

👉 Si el script usa el DOM → defer
👉 Si es independiente → async
👉 Si no sabés → defer

5.4. Relación entre atributos defer y async y DOMContentLoaded vs load

  • defer reemplaza en la práctica a DOMContentLoaded.
  • async es solo para scripts independientes.
  • load se usa solo cuando se depende de recursos externos.

6. Orden de ejecución de DOMContentLoaded, load, defer y async.

El navegador no ejecuta todo a la vez. Sigue una línea de tiempo estricta que depende de dónde está el script y qué atributos usa.

6.1. Orden base del navegador (sin scripts)

1. Recibe HTML
2. Parseo del HTML
3. Construcción del DOM
4. DOMContentLoaded
5. Carga de recursos
6. load

Esto es el esqueleto base.

6.2. Script normal (sin defer ni async)

HTML

<script src="app.js"></script>Lenguaje del código: HTML, XML (xml)

Orden real:

HTML parseándose
↓
Encuentra <script>
↓
PAUSA el parseo
↓
Descarga app.js
↓
Ejecuta app.js
↓
Continúa parseo HTML
↓
DOM construido
↓
DOMContentLoaded
↓
loadLenguaje del código: HTML, XML (xml)

📌 Bloquea HTML
📌 Puede romper acceso al DOM

6.3. Script con defer

HTML

<script src="app.js" defer></script>
Lenguaje del código: HTML, XML (xml)

Orden real:

HTML parseándose
↓
Encuentra script defer
↓
Descarga en paralelo
↓
HTML sigue parseándose
↓
DOM construido
↓
Ejecuta script defer
↓
DOMContentLoaded
↓
load

📌 No bloquea HTML
📌 DOM siempre disponible
📌 Respeta el orden entre scripts defer

6.4. Script con async

HTML

<script src="app.js" async></script>
Lenguaje del código: HTML, XML (xml)

Orden real (NO determinístico):

HTML parseándose
↓
Descarga script async en paralelo
↓
(termina descarga)
↓
EJECUTA script (pausa HTML)
↓
HTML continúa
↓
DOM construido
↓
DOMContentLoaded
↓
load
Lenguaje del código: JavaScript (javascript)

⚠️ Puede ejecutarse:

  • Antes del DOM
  • Durante el parseo
  • Después del DOM

📌 NO garantiza orden
📌 NO es seguro para DOM

6.5. DOMContentLoaded

document.addEventListener('DOMContentLoaded', () => {
  console.log('DOM listo');
});Lenguaje del código: JavaScript (javascript)

Cuándo ocurre:

  • DOM completamente construido
  • Scripts defer ya ejecutados
  • No espera imágenes

6.6. load

window.addEventListener('load', () => {
  console.log('Todo cargado');
});Lenguaje del código: JavaScript (javascript)

Cuándo ocurre:

  • DOM listo
  • CSS cargado
  • Imágenes cargadas
  • Recursos externos cargados.

7. Ejemplo de DOMContentLoaded vs load con imagen.

ejemplo de DOMContentLoaded vs load

Veamos la imagen pensando en estos dos hitos (DOMContentLoaded vs load )como «La Estructura» vs. «El Contenido Total»:

7.1. El Hito Verde: DOMContentLoaded (La Estructura Lista)

Fijate que el rayo verde aparece justo cuando termina la flecha azul de «HTML Parsing».

  1. ¿Qué significa en la imagen?:
    • El navegador ya terminó de leer el «plano» de la casa (tu archivo .html). Ya sabe que hay un <body>, dos <div> y un <button>. Por eso ves el árbol de nodos arriba de la flecha.
  2. El detalle clave:
    • Mirá la línea naranja que está abajo. Las imágenes y el CSS todavía están «en camino» (están a la izquierda del rayo verde).
  3. Tu ventaja como programador:
    • En este punto exacto, ya podés «darle órdenes» al botón. No necesitás esperar a que las fotos carguen para que el botón sepa qué hacer cuando alguien le dé clic.
  4. En resumen:
    • Es el evento de la velocidad.

7.2. El Hito Rojo: window.load (El Contenido Total)

Ahora mirá el «Pin» rojo al final de la derecha. Notá que hay una línea de puntos que lo conecta con el final de la línea naranja.

  1. ¿Qué significa en la imagen?:
    • Este evento no se dispara hasta que la línea naranja (recursos externos) llega a su fin.
  2. El detalle clave:
    • Solo ocurre cuando las imágenes pesadas y los archivos CSS terminaron de descargarse. Si tenés una foto de 10MB, el pin rojo se moverá mucho más hacia la derecha, alejándose del rayo verde.
  3. Tu ventaja como programador:
    • Usalo solo si necesitás que la página esté «estéticamente perfecta» o si necesitás medir cuánto mide la foto en pantalla (porque antes de este punto, la foto «no existe» físicamente para el navegador, solo existe su etiqueta).
  4. En resumen:
    • Es el evento de la totalidad.

7.3. ¿Cuál es la diferencia más importante según la imagen?

Si te fijas en el espacio que hay entre el rayo verde y el pin rojo, ese es el «Tiempo de Espera del Usuario».

  • Si programas tus botones en el rayo verde (DOMContentLoaded), el usuario siente que la página es rápida.
  • Si programas tus botones en el pin rojo (load), el usuario siente que la página es lenta porque el botón «no responde» hasta que cargó la última foto del pie de página.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *