acerca de HTML

Referencia de etiquetas

Etiqueta progress en HTML: avance e indeterminación

La etiqueta <progress> representa el avance de una tarea: puede indicar cuánto se ha completado o un estado indeterminado cuando no se conoce el trabajo restante. Úsala para lecciones completadas, una instalación o una carga cuyo avance puedas obtener. La barra comunica ese estado; no realiza la tarea ni calcula su progreso por sí sola.

Ejemplo mínimo: tres lecciones de cinco

<label for="avance">Lecciones completadas: 3 de 5</label>
<progress id="avance" value="3" max="5">3 de 5</progress>

El avance es 3 ÷ 5 = 0,6, es decir, el 60 %. El navegador representa la proporción con una barra y la etiqueta deja visible la cantidad. for="avance" asocia el nombre con el elemento de id="avance". El porcentaje no aparece escrito automáticamente.

Para probarlo, sustituye el contenido de <body> del documento completo del caso práctico por este fragmento. Cambia value a 4 y ambos textos a «4 de 5»: la barra pasa al 80 %. Si retiras las etiquetas de apertura y cierre de <progress> y conservas su texto, permanece la cantidad escrita, pero desaparecen la barra y la semántica de avance.

Sintaxis y contexto válido

<progress> lleva apertura y cierre; ninguna de las dos etiquetas puede omitirse. Se utiliza donde se admite contenido de frase, por ejemplo dentro de un párrafo. Su interior admite texto y elementos de frase, pero ningún <progress> descendiente. No pongas un <div> ni otro indicador dentro. Estas reglas se definen en el HTML Living Standard.

No necesita estar en un formulario, no es un campo editable y no envía por sí mismo un valor. Añade una etiqueta visible que identifique la tarea: el texto interior sirve de alternativa para navegadores antiguos, pero no proporciona el nombre accesible ni suele aparecer junto a la barra.

Progreso determinado e indeterminado

En una tarea de cinco fases conocidas, value="0" max="5" significa cero fases completadas. Es progreso determinado, aunque la barra esté vacía.

Si una operación sigue en curso y todavía no puedes medir cuánto falta, omite value:

<label for="preparacion">Preparación: duración desconocida</label>
<progress id="preparacion">En preparación</progress>
<p>La preparación continúa; todavía no hay un porcentaje disponible.</p>

El navegador puede mostrar un indicador animado, según su presentación. Este fragmento solo ilustra el estado indeterminado: no inicia una preparación real. No inventes un porcentaje a partir del tiempo transcurrido si no conoces el trabajo total.

Para pasar a ese estado desde JavaScript, utiliza barra.removeAttribute("value"). Para volver a un avance conocido, define el máximo adecuado y asigna barra.value = 2, por ejemplo. Escribir value="0" o dejar value="" no produce indeterminación: el atributo sigue presente. La referencia de progress en MDN explica esta diferencia.

Atributos y propiedades

Los atributos específicos son dos:

  • value: trabajo completado, como número entre 0 y max. Su ausencia indica progreso indeterminado.
  • max: trabajo total; debe ser un número mayor que 0. Si se omite, su valor predeterminado es 1, no 100.

No existe un atributo específico min: el mínimo es siempre 0. Usa números sin unidades ni %, y punto para decimales. Así, value="0.6" sin max expresa el 60 %; value="60" max="100" expresa la misma proporción. Mantén los valores dentro del rango aunque el navegador ajuste entradas inválidas.

id, class y lang son atributos globales. Una propiedad CSS como width cambia la anchura visual. En JavaScript, las propiedades DOM .value y .max modifican los valores; .position permite consultar la fracción completada y devuelve −1 en estado indeterminado. .value devuelve 0 también en ese estado: por sí sola no permite distinguirlo del comienzo de una tarea. Consulta la interfaz HTMLProgressElement.

Caso práctico: completar cinco fases con JavaScript

Guarda el siguiente código como fases.html, en UTF-8, y ábrelo en el navegador. Incluye todo lo necesario; no requiere CSS, archivos adicionales ni servidor. Cada activación del botón simula una fase terminada. No sube archivos ni mide una descarga real.

<!doctype html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Cinco fases de una demostración</title>
</head>
<body>
  <h1>Completar cinco fases</h1>
  <p>Demostración local: cada pulsación completa una fase ficticia.</p>
  <p>
    <label for="fases-avance">Fases de la demostración</label>
    <progress id="fases-avance" value="0" max="5"
      aria-describedby="fases-detalle">0 de 5</progress>
  </p>
  <p id="fases-detalle">0 de 5 fases completadas (0 %).</p>
  <button id="fases-completar" type="button" disabled>
    Completar una fase
  </button>
  <p id="fases-aviso" role="status"></p>
  <noscript>
    <p>El botón necesita JavaScript. La demostración permanece en 0 de 5.
      Para probar otro valor, edita value y los textos del archivo.</p>
  </noscript>

  <h2>Un estado indeterminado de muestra</h2>
  <label for="fases-espera">Preparación: duración desconocida</label>
  <progress id="fases-espera">En preparación</progress>
  <p>Esta barra ilustra una tarea sin porcentaje conocido;
    no hay ninguna operación remota en curso.</p>

  <script>
    const barra = document.getElementById("fases-avance");
    const detalle = document.getElementById("fases-detalle");
    const boton = document.getElementById("fases-completar");
    const aviso = document.getElementById("fases-aviso");

    boton.disabled = false;
    boton.addEventListener("click", () => {
      barra.value = Math.min(barra.value + 1, barra.max);
      const porcentaje = Math.round(100 * barra.value / barra.max);
      barra.textContent = `${barra.value} de ${barra.max}`;
      detalle.textContent =
        `${barra.value} de ${barra.max} fases completadas (${porcentaje} %).`;

      if (barra.value === barra.max) {
        boton.disabled = true;
        aviso.textContent = "Demostración terminada: las cinco fases están completas.";
      }
    });
  </script>
</body>
</html>

Prueba el ejemplo paso a paso:

  1. Pulsa Tab hasta el botón y actívalo con Enter o Espacio. Cada activación aumenta una fase y actualiza el texto: 20 %, 40 %, 60 %, 80 % y 100 %.
  2. En la quinta fase, la barra queda completa, aparece el aviso final y el botón se deshabilita. Recarga para comenzar de nuevo.
  3. Retira value del segundo indicador si lo habías añadido: vuelve al estado indeterminado. Añade value="0" para compararlo con una barra determinada vacía.
  4. Desactiva JavaScript y recarga. El primer avance permanece en 0 de 5, el botón está deshabilitado y aparece la explicación alternativa; el segundo indicador mantiene su estado indeterminado.

Cambiar .value no sincroniza automáticamente los textos: el script actualiza tanto el mensaje visible como el contenido alternativo de la barra. En una aplicación real, sustituye el incremento ficticio por información de la operación que estés siguiendo.

Accesibilidad y mensajes de estado

Utiliza una <label> asociada y conserva la cantidad visible fuera del indicador. No añadas role="progressbar" ni aria-valuenow para recrear la semántica que ya aporta <progress>. El indicador no es un control para introducir datos y no necesita una parada de Tab.

En el ejemplo, el contador visible no es una región viva. Solo el aviso final usa role="status", cuyo anuncio es cortés según WAI-ARIA. Esto evita solicitar un anuncio adicional por cada fase. Para operaciones con actualizaciones muy frecuentes, comunica hitos útiles en vez de anunciar cada cambio. El anuncio concreto depende del navegador y del lector de pantalla; revisa nombre, valores y mensajes con las herramientas y tecnologías de asistencia que vayas a utilizar.

Errores frecuentes y etiquetas relacionadas

¿Cómo hago progreso indeterminado? Omite o retira value; cero significa un avance conocido que todavía no ha comenzado.

¿Progress y meter son equivalentes? No. <meter> representa una medición dentro de un rango, como 60 GB de disco usado. <progress> representa la parte completada de una tarea, como tres de cinco fases.

Si la barra parece llena demasiado pronto, comprueba max: su predeterminado es 1. Revisa después el rango y que los números no lleven porcentajes o comas decimales. Si no cambia, verifica que el evento se ejecuta y que el script selecciona el ID correcto. Un nombre ausente exige comprobar la coincidencia entre for e id y evitar IDs duplicados.

<button> activa la acción del ejemplo; <output> puede expresar un resultado calculado, pero no sustituye la semántica de avance. Una barra animada tampoco demuestra que exista una descarga: necesitas datos de esa operación.

Compatibilidad y fuentes

Consultado el 3 de octubre de 2026: <progress> y la interfaz utilizada tienen soporte amplio en navegadores actuales, según la compatibilidad del elemento en MDN y la referencia de HTMLProgressElement enlazada antes. La forma y la animación pueden variar; los textos mantienen comprensible el estado. El HTML Living Standard fija el significado y las restricciones de autoría, independientemente del aspecto de la barra.