W3docs

Etiqueta HTML <progress>

La etiqueta <progress> muestra el indicador de progreso de una tarea (barra de progreso). Ejemplos de uso.

La etiqueta <progress> es uno de los elementos HTML5. Representa el progreso de finalización de una tarea — cuánto de una operación (carga de archivo, descarga, paso de formulario, instalación) se ha completado hasta el momento. El navegador dibuja una barra de progreso cuyo relleno refleja el value relativo al max.

Como <progress> solo describe qué tan avanzado está algo, los valores reales suelen cambiar en tiempo de ejecución. Los actualizas con JavaScript (consulta el ejemplo dinámico a continuación). La apariencia exacta del elemento varía según el navegador y el sistema operativo.

<progress> vs <meter>

Estos dos elementos se ven similares pero significan cosas diferentes — elige según la intención, no por la apariencia:

Usa <progress> cuando…Usa <meter> cuando…
Estás mostrando qué tan completa está una tarea (avanza hacia su finalización).Estás mostrando una medición estática dentro de un rango conocido, como el uso del disco, una puntuación o la relevancia de un resultado de búsqueda.
El valor crece naturalmente de 0 a max con el tiempo.El valor se ubica en algún punto de una escala fija y no está "en progreso".

Una regla general: si puedes terminarlo, usa <progress>. Si solo estás midiendo un nivel, usa <meter>.

Sintaxis

La etiqueta <progress> viene en pares. El contenido se escribe entre las etiquetas de apertura (<progress>) y cierre (</progress>).

Ejemplo de la etiqueta HTML <progress>:

Etiqueta HTML <progress>

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <label for="file">Loading:</label>
    <progress id="file" value="35" max="100">35%</progress>
  </body>
</html>

Resultado

progress tag example

El texto entre las etiquetas (35% arriba) es contenido alternativo: los navegadores que soportan <progress> lo ignoran y dibujan la barra, mientras que los navegadores muy antiguos que no reconocen el elemento muestran el texto en su lugar. Es una buena práctica mantenerlo sincronizado con el valor actual.

Accesibilidad: siempre etiqueta tu barra de progreso

Una barra <progress> sin etiquetar es anunciada por los lectores de pantalla como un porcentaje sin contexto — "35 por ciento" no le dice al usuario nada sobre qué se está cargando. Proporciona un nombre accesible de una de estas formas:

  • Un <label> cuyo for coincida con el id de la barra (como arriba). Hacer clic en la etiqueta también es una conveniencia útil.
  • aria-labelledby apuntando al id de un texto visible.
  • aria-label="…" cuando no hay texto visible al que hacer referencia.
<!-- Visible label referenced by the bar -->
<span id="upload-status">Uploading photos</span>
<progress aria-labelledby="upload-status" value="60" max="100">60%</progress>

<!-- No visible text? Use aria-label -->
<progress aria-label="Uploading photos" value="60" max="100">60%</progress>

Determinado vs indeterminado

Una barra de progreso puede ser determinada o indeterminada.

  • Determinada — sabes qué tan avanzada está la tarea, por lo que proporcionas un value. La barra se llena proporcionalmente (value ÷ max).
  • Indeterminada — sabes que la tarea está en ejecución pero no cuánto falta, por lo que omites el atributo value. El navegador muestra una barra de "actividad" animada (una franja en movimiento o pulso) en lugar de un relleno fijo.

Ejemplo indeterminado

Omite value para obtener el estado indeterminado y luego establécelo una vez que conozcas el número real:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <label for="task">Working:</label>
    <!-- No value attribute → indeterminate (animated) -->
    <progress id="task" max="100">Working…</progress>
  </body>
</html>

Esto es ideal mientras esperas una respuesta del servidor y aún no puedes calcular un porcentaje. En cuanto puedas, cambia el mismo elemento a determinado estableciendo value desde JavaScript (progress.value = 40).

Estilos para determinado vs indeterminado

Es más fácil aplicar estilos a la barra indeterminada, ya que no tiene el atributo value — puedes apuntarla con el selector de negación de CSS progress:not([value]).

La barra determinada se apunta con el selector progress[value]. Agrega dimensiones con las propiedades CSS width y height y establece appearance en none:

Estilos para barras de progreso

La forma moderna simple: accent-color

Para la mayoría de los casos, ya no necesitas prefijos de proveedor ni pseudoelementos. Establece la propiedad CSS accent-color y todos los navegadores modernos colorean la barra de forma consistente con una sola línea:

progress {
  accent-color: #2563eb; /* color of the filled portion */
  width: 200px;
}

Recurre a los pseudoelementos con prefijo a continuación solo cuando necesites control total sobre la pista, degradados personalizados o debas soportar motores más antiguos.

Chrome, Safari y la última versión de Opera (16+) pertenecen a esta categoría. El estilo de la apariencia del elemento <progress> se puede hacer con el uso de -webkit-appearance: progress-bar.

Establece -webkit-appearance: none; para restablecer los estilos predeterminados.

Ejemplo de una barra de progreso

progress[value] {
  -webkit-appearance: none;
  appearance: none;
  width: 200px;
  height: 15px;
}

Ejemplo del estado determinado de la barra de progreso:

Ejemplo de una barra de progreso determinada:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      progress[value] {
        -webkit-appearance: none;
        appearance: none;
        width: 200px;
        height: 15px;
      }
    </style>
  </head>
  <body>
    <label for="file">Loading:</label>
    <progress id="file" value="30" max="100">30%</progress>
  </body>
</html>

Después de esto, puede haber problemas porque diferentes navegadores proporcionan pseudoelementos separados para dar estilo a la barra de progreso. Para resolver este problema, puedes usar alternativas (fallbacks).

WebKit/Blink proporciona dos pseudoelementos:

  • ::-webkit-progress-bar, que aplica estilo al contenedor del elemento progress.
  • ::-webkit-progress-value, que aplica estilo al valor dentro de la barra de progreso.

Aplica estilo a ::-webkit-progress-bar con diferentes propiedades CSS:

Ejemplo de una barra de progreso

progress[value]::-webkit-progress-bar {
  background-color: #eee;
  border-radius: 2px;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.26) inset;
}

Aplica estilo a ::-webkit-progress-value, que es lo mismo que la barra, con varios fondos degradados para diferentes propósitos. Usa el prefijo -webkit- para los degradados:

webkit-progress-value

progress[value]::-webkit-progress-value {
  background-image: -webkit-linear-gradient(-45deg, transparent 33%, rgba(0, 0, 0, .2) 33%, rgba(0, 0, 0, .2) 66%, transparent 66%), -webkit-linear-gradient(top, rgba(255, 255, 255, .25), rgba(0, 0, 0, .25)), -webkit-linear-gradient(left, #1000ff, #359900);
  border-radius: 4px;
  background-size: 20px 15px, 100% 100%, 100% 100%;
}

Ejemplo de la etiqueta HTML <progress> usada con propiedades CSS:

Ejemplo de la etiqueta HTML <progress> con propiedades CSS:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      progress[value] {
        -webkit-appearance: none;
        appearance: none;
        width: 200px;
        height: 15px;
      }
      progress[value]::-webkit-progress-bar {
        background-color: #cccccc;
        border-radius: 4px;
      }
      progress[value]::-webkit-progress-value {
        background-image: -webkit-linear-gradient(-45deg, transparent 33%, rgba(0, 0, 0, .2) 33%, rgba(0, 0, 0, .2) 66%, transparent 66%), -webkit-linear-gradient(top, rgba(255, 255, 255, .25), rgba(0, 0, 0, .25)), -webkit-linear-gradient(left, #1000ff, #359900);
        border-radius: 4px;
        background-size: 20px 15px, 100% 100%, 100% 100%;
      }
    </style>
  </head>
  <body>
    <span>Loading:</span>
    <progress value="55" max="100" aria-label="Loading progress"></progress>
  </body>
</html>

Firefox

Al usar appearance: none podemos eliminar el bisel y el relieve predeterminados. Sin embargo, esto deja un pequeño borde en Firefox, que se puede eliminar usando border: none. Esto también resuelve el problema del borde con Opera 12.

Ejemplo de la barra <progress> en Firefox

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      progress[value] {
        -webkit-appearance: none;
        -moz-appearance: none;
        appearance: none;
        border: none;
        width: 200px;
        height: 15px;
      }
    </style>
  </head>
  <body>
    <span>Loading:</span>
    <progress value="55" max="100" aria-label="Loading progress"></progress>
  </body>
</html>

Firefox proporciona un único pseudoelemento (::-moz-progress-bar) que se puede usar para apuntar al valor de la barra de progreso. En otras palabras, no podemos aplicar estilo al fondo del contenedor en Firefox.

Etiqueta HTML <progress> - Firefox

progress[value]::-moz-progress-bar {
  background-image: -moz-linear-gradient( 135deg, transparent 33%, rgba(0, 0, 0, 0.1) 33%, rgba(0, 0, 0, 0.1) 66%, transparent 66%), -moz-linear-gradient( top, rgba(255, 255, 255, 0.25), rgba(0, 0, 0, 0.25)), -moz-linear-gradient( left, #ff00f7, #4e922a);
  background-size: 35px 20px, 100% 100%, 100% 100%;
}

Firefox no soporta los pseudoelementos ::before o ::after en la barra de progreso, y no permite la animación CSS3 keyframe en la barra de progreso, lo que reduce la experiencia.

Ejemplo de la etiqueta HTML <progress> para Firefox:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
    <style>
      progress[value]::-moz-progress-bar {
        background-image: -moz-linear-gradient( 135deg, transparent 33%, rgba(0, 0, 0, 0.1) 33%, 
                          rgba(0, 0, 0, 0.1) 66%, transparent 66%), 
                          -moz-linear-gradient( top, rgba(255, 255, 255, 0.25), 
                          rgba(0, 0, 0, 0.25)),
                          -moz-linear-gradient( left, #ff00f7, #4e922a);
        background-size: 35px 20px, 100% 100%, 100% 100%;
      }
    </style>
  </head>
  <body>
    <span>Loading:</span>
    <progress value="35" max="100" aria-label="Loading progress"></progress>
  </body>
</html>

Actualización de una barra de progreso con JavaScript

Dado que un elemento <progress> real expone una propiedad value, actualizas la barra simplemente asignándole un número — el navegador redibuja el relleno por ti. Aquí un temporizador simula una descarga que avanza de 0 a 100 y luego se detiene:

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <label for="download">Downloading:</label>
    <progress id="download" value="0" max="100">0%</progress>
    <span id="status">0%</span>

    <script>
      var bar = document.getElementById("download");
      var status = document.getElementById("status");
      var loaded = 0;

      var timer = setInterval(function () {
        loaded += 5;
        bar.value = loaded;          // moves the bar
        status.textContent = loaded + "%";
        if (loaded >= bar.max) {
          clearInterval(timer);
        }
      }, 300);
    </script>
  </body>
</html>

Para cambiar una barra de indeterminada a determinada en tiempo de ejecución, establece su value una vez que conozcas el número real (bar.value = 40). Para volver a indeterminada, elimina el atributo con bar.removeAttribute("value").

Barra de progreso de desplazamiento (alternativa solo con CSS)

El elemento a continuación está construido con <div>s con estilo, no es un elemento <progress> real. Es un patrón común para un indicador de desplazamiento de página donde deseas control total sobre la apariencia. Si prefieres un elemento semántico, podrías reemplazar el <div> por un <progress> y actualizar su value en el controlador de desplazamiento en su lugar.

Así es como crear una barra que muestra qué tan lejos has desplazado la página:

ejemplo de cómo crear una barra de progreso que muestra qué tan lejos has desplazado la página

<!DOCTYPE html>
<html>
  <head>
    <style>
      #progress-bar {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 5px;
        background-color: #ddd;
      }

      #progress-bar-fill {
        height: 100%;
        background-color: blue;
        width: 0%;
      }
    </style>
  </head>
  <body>
    <div id="progress-bar">
      <div id="progress-bar-fill"></div>
    </div>

    <h1>Scrollable Content</h1>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor quam non felis interdum pellentesque. Suspendisse potenti. Nullam molestie neque in justo consectetur, sit amet varius arcu malesuada. Fusce sed laoreet ipsum. Nulla
      facilisi. Donec eleifend auctor purus, eu bibendum risus facilisis sit amet.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor quam non felis interdum pellentesque. Suspendisse potenti. Nullam molestie neque in justo consectetur, sit amet varius arcu malesuada. Fusce sed laoreet ipsum. Nulla
      facilisi. Donec eleifend auctor purus, eu bibendum risus facilisis sit amet.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor quam non felis interdum pellentesque. Suspendisse potenti. Nullam molestie neque in justo consectetur, sit amet varius arcu malesuada. Fusce sed laoreet ipsum. Nulla
      facilisi. Donec eleifend auctor purus, eu bibendum risus facilisis sit amet.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor quam non felis interdum pellentesque. Suspendisse potenti. Nullam molestie neque in justo consectetur, sit amet varius arcu malesuada. Fusce sed laoreet ipsum. Nulla
      facilisi. Donec eleifend auctor purus, eu bibendum risus facilisis sit amet.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor quam non felis interdum pellentesque. Suspendisse potenti. Nullam molestie neque in justo consectetur, sit amet varius arcu malesuada. Fusce sed laoreet ipsum. Nulla
      facilisi. Donec eleifend auctor purus, eu bibendum risus facilisis sit amet.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor quam non felis interdum pellentesque. Suspendisse potenti. Nullam molestie neque in justo consectetur, sit amet varius arcu malesuada. Fusce sed laoreet ipsum. Nulla
      facilisi. Donec eleifend auctor purus, eu bibendum risus facilisis sit amet.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor quam non felis interdum pellentesque. Suspendisse potenti. Nullam molestie neque in justo consectetur, sit amet varius arcu malesuada. Fusce sed laoreet ipsum. Nulla
      facilisi. Donec eleifend auctor purus, eu bibendum risus facilisis sit amet.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor quam non felis interdum pellentesque. Suspendisse potenti. Nullam molestie neque in justo consectetur, sit amet varius arcu malesuada. Fusce sed laoreet ipsum. Nulla
      facilisi. Donec eleifend auctor purus, eu bibendum risus facilisis sit amet.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor quam non felis interdum pellentesque. Suspendisse potenti. Nullam molestie neque in justo consectetur, sit amet varius arcu malesuada. Fusce sed laoreet ipsum. Nulla
      facilisi. Donec eleifend auctor purus, eu bibendum risus facilisis sit amet.
    </p>
    <p>
      Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed auctor quam non felis interdum pellentesque. Suspendisse potenti. Nullam molestie neque in justo consectetur, sit amet varius arcu malesuada. Fusce sed laoreet ipsum. Nulla
      facilisi. Donec eleifend auctor purus, eu bibendum risus facilisis sit amet.
    </p>

    <script>
      window.addEventListener("scroll", function () {
        var progressBarFill = document.getElementById("progress-bar-fill");
        var scrollPosition = window.scrollY;
        var totalHeight = document.body.scrollHeight - window.innerHeight;
        var percentage = (scrollPosition / totalHeight) * 100;
        progressBarFill.style.width = percentage + "%";
      });
    </script>
  </body>
</html>

En este ejemplo, tenemos un div con posición fija con un id de progress-bar que sirve como contenedor. Dentro de él, otro div con un id de progress-bar-fill sirve como el relleno en movimiento. (Dado que este es un indicador de desplazamiento decorativo en lugar de una tarea, un <div> simple es aceptable aquí; un <progress> real también funcionaría si estableces su value en el mismo controlador.)

Hemos usado CSS para establecer el ancho y alto iniciales de la barra de progreso, así como los colores de fondo para la barra de progreso y el relleno de la barra de progreso.

También hemos incluido un evento de escucha de JavaScript que escucha el evento scroll en el objeto window. Cuando el usuario desplaza la página, calculamos la posición de desplazamiento y la altura total de la página, y luego calculamos el porcentaje de la página que se ha desplazado. Actualizamos la propiedad width del elemento progress-bar-fill para reflejar este porcentaje, actualizando así la barra de progreso.

Puedes copiar este código en un nuevo archivo HTML y abrirlo en tu navegador web para ver cómo se ve. A medida que desplazas la página hacia abajo, la barra de progreso se actualizará para reflejar qué tan lejos has desplazado. Puedes ajustar la altura y el color de la barra de progreso según tus necesidades.

Atributos

AtributoValorDescripción
maxnumberDefine el valor máximo del proceso actual. El valor puede ser un número positivo mayor que 0.
valuenumberDefine el tamaño de la tarea completada. El valor puede ser un número de 0 al número indicado en el atributo max, o un número en el rango de 0 a 1 si el atributo max no está especificado.

La etiqueta <progress> también admite los Atributos Globales y los Atributos de Evento.

Práctica

Práctica
¿Qué representa la etiqueta HTML progress?
¿Qué representa la etiqueta HTML progress?
Was this page helpful?