W3docs

Etiqueta HTML <script>

La etiqueta HTML <script> incrusta o enlaza JavaScript en una página. Aprende src, async vs defer, type="module", ubicación y atributos con ejemplos.

La etiqueta HTML <script> declara scripts del lado del cliente — casi siempre JavaScript — en un documento HTML. Los scripts añaden interactividad: validación de formularios, actualizaciones dinámicas de contenido, manipulación de imágenes y respuesta a eventos del usuario. La etiqueta puede contener el script en línea (entre las etiquetas de apertura y cierre) o cargar un archivo externo mediante el atributo src. Para una visión general más amplia sobre cómo agregar scripts a una página, consulta HTML scripts.

Peligro

Si conectas un archivo externo con scripts, no incrustes código en la misma etiqueta <script>.

La etiqueta HTML <script> puede colocarse en el elemento <head>, así como dentro del elemento <body>. Los scripts que deben ejecutarse primero se colocan habitualmente en el elemento <head> con defer, o al final del elemento <body>. La etiqueta <script> puede usarse muchas veces en un documento HTML.

Una etiqueta script dentro de un documento HTML enlazando a JavaScript externo

Sintaxis

La etiqueta <script> siempre viene en pares — una apertura <script> y un cierre </script>. El código en línea va entre ellas; para un archivo externo, deja la etiqueta vacía y apunta src al archivo:

<script>
  // inline JavaScript here
  console.log("Hello from inline script");
</script>

<script src="app.js"></script>

Ejemplo de script en línea

Para seleccionar un elemento HTML, JavaScript usa comúnmente el método document.getElementById():

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <p id="example"></p>
    <script>
      document.getElementById("example").innerHTML = "My first JavaScript code";
    </script>
  </body>
</html>

Cargar un script externo

En proyectos reales casi siempre se mantiene el JavaScript en un archivo .js separado y se carga con src. Esto mantiene el HTML limpio, permite que el navegador almacene el script en caché y posibilita reutilizar el mismo archivo en varias páginas:

<script src="app.js" defer></script>

Algunos aspectos a tener en cuenta:

  • No mezcles ambas formas. Cuando src está presente, cualquier código escrito entre las etiquetas es ignorado. Usa código en línea o un src, pero no ambos en la misma etiqueta.
  • type="text/javascript" es innecesario. JavaScript es el lenguaje de scripting predeterminado en el HTML moderno, por lo que puedes omitir type completamente. Solo establece type cuando realmente necesites type="module" (ver más abajo).
  • charset no tiene efecto en scripts externos hoy en día. La codificación de caracteres se obtiene del encabezado HTTP Content-Type del archivo (y de la propia codificación de la página), así que el atributo charset en <script> está obsoleto — no confíes en él.

async vs. defer

Por defecto, cuando el navegador encuentra un <script src="..."> mientras analiza el HTML, detiene el análisis, descarga el script, lo ejecuta y solo entonces continúa. Esto bloquea el renderizado. Los atributos boolean async y defer solucionan esto — ambos descargan el script en paralelo sin bloquear el análisis — pero difieren en cuándo se ejecuta el script:

Atributo¿Bloquea el análisis?Cuándo se ejecutaOrden
(ninguno)Inmediatamente al encontrarloEn orden del documento
deferNoDespués de que el HTML se haya analizado completamente, justo antes de DOMContentLoadedEn orden del documento
asyncNoEn cuanto termina de descargarseEl que termine primero (sin orden garantizado)
<!-- Runs after the page is parsed, in order. Safe for code that touches the DOM. -->
<script src="app.js" defer></script>

<!-- Runs as soon as it loads, order not guaranteed. Good for independent scripts
     like analytics that don't depend on other scripts or the parsed DOM. -->
<script src="analytics.js" async></script>

Usa defer cuando los scripts dependen del DOM o entre sí (el caso más común). Usa async para scripts independientes y sin orden específico, como píxeles de seguimiento.

Información

async y defer son atributos boolean — su mera presencia los activa. Escríbelos sin valor (defer), no en el antiguo estilo XHTML defer="defer". Lo mismo aplica a otros atributos boolean como disabled y checked. Ambos atributos son ignorados en scripts en línea (aquellos sin src).

Ubicación del script: <head> vs. final de <body>

Dónde coloques <script> importa porque un script normal bloquea el análisis:

  • <head> con defer — la recomendación moderna. La descarga comienza de forma temprana mientras el HTML se sigue analizando, y la ejecución espera hasta que el DOM está listo. Obtienes una carga rápida sin bloqueos.
  • Final de <body> — el enfoque clásico. Cuando el analizador llega al script, el DOM completo ya existe, por lo que el script puede consultar elementos de forma segura. No se necesita ningún atributo.
<head>
  <script src="app.js" defer></script>
</head>
<body>
  <!-- page content -->
</body>

Evita un <script src> normal (sin async/defer) en <head>, ya que bloquea el renderizado de la página hasta que el script se descarga y ejecuta.

Módulos ES con type="module"

Establecer type="module" convierte el script en un módulo ES. Los scripts de módulo se comportan de forma diferente a los scripts clásicos:

  • Soportan import / export, por lo que puedes dividir el código en varios archivos.
  • Son diferidos por defecto — los scripts de módulo siempre esperan hasta que el HTML está analizado (no se necesita defer).
  • Siempre se ejecutan en modo estricto, y tienen su propio ámbito de nivel superior (las variables no se filtran al objeto global).
<script type="module" src="main.js"></script>

<script type="module">
  import { greet } from "./greet.js";
  greet("World");
</script>

Para compatibilidad con navegadores muy antiguos que no entienden los módulos, puedes combinar un módulo con un script de reserva nomodule — los navegadores modernos ejecutan el módulo e ignoran el de reserva, los más antiguos hacen lo contrario.

Una nota sobre XHTML y el marcado heredado

En el HTML moderno no necesitas un atributo type, y no envuelves el contenido de scripts en línea en una sección CDATA. Ese envoltorio //<![CDATA[ ... //]]> solo era relevante en XHTML, donde el contenido del script se analizaba como marcado y los caracteres especiales como < y & debían escaparse o protegerse. Si estás escribiendo HTML estándar, puedes ignorarlo.

Atributos

AtributoValorDescripción
srcURLURL de un archivo de script externo (relativa o absoluta).
async(boolean)El script externo se obtiene en paralelo y se ejecuta en cuanto está disponible, sin bloquear el análisis.
defer(boolean)El script externo se obtiene en paralelo y se ejecuta, en orden, después de que el HTML esté analizado.
typetipo de medioGeneralmente omitido (JavaScript es el predeterminado). Establécelo como module para cargar un módulo ES.
charsetcharsetObsoleto — no tiene efecto; la codificación proviene del Content-Type HTTP del archivo.
crossoriginanonymous | use-credentialsConfigura CORS para la solicitud del script externo.
integrityhashHash de Subresource Integrity usado para verificar el script descargado.

La etiqueta <script> admite los Atributos globales y los Atributos de eventos.

Práctica

Práctica
¿Qué atributo permite que un script externo se descargue sin bloquear el análisis y se ejecute, en orden, después de que el HTML esté analizado?
¿Qué atributo permite que un script externo se descargue sin bloquear el análisis y se ejecute, en orden, después de que el HTML esté analizado?
Was this page helpful?