Tema 12 · Spinners y Carga

Spinners y Marcadores de Carga

Aprende a indicar operaciones asíncronas en curso mediante giradores circulares con .spinner-border, pulsos con .spinner-grow y botones con estado de carga interactivo.

Giradores Circulares (.spinner-border)

Los spinners de Bootstrap 5 están construidos exclusivamente con HTML y CSS3 puro (sin imágenes GIF pesadas ni librerías externas), lo que permite colorearlos con cualquier clase semántica de texto (.text-primary, .text-success, etc.).

<div class="spinner-border text-primary" role="status">
  <span class="visually-hidden">Cargando...</span>
</div>

Efecto de Pulso (.spinner-grow)

En lugar de girar, la variante .spinner-grow late repetidamente expandiéndose y desvaneciéndose en un suave ciclo visual:

<div class="spinner-grow text-success" role="status">
  <span class="visually-hidden">Enviando datos...</span>
</div>

Spinners dentro de Botones de Envío

El patrón estándar en aplicaciones web modernas consiste en incrustar un spinner reducido (.spinner-border-sm) dentro del botón al enviar un formulario para deshabilitar clics duplicados mientras se espera la respuesta del servidor:

<button class="btn btn-primary" type="button" disabled>
  <span class="spinner-border spinner-border-sm" aria-hidden="true"></span>
  <span role="status">Guardando cambios...</span>
</button>

⚡ Botón con Estado de Carga Dinámico (Loading Spinner)

Haz clic en el botón de sincronización para simular una petición HTTP con activación y desactivación de spinner en vivo:

index.html
Solo lectura
<!DOCTYPE html>
<html lang="es">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Spinners en Bootstrap 5</title>
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body class="bg-light p-4">

  <div class="container" style="max-width: 600px;">
    <div class="card shadow-sm border-0 rounded-4 p-4 bg-white text-center">
      <h4 class="fw-bold text-dark mb-3">Indicadores de Proceso Asíncrono</h4>

      <!-- 1. Galería de Spinners Circulares -->
      <div class="d-flex justify-content-center gap-3 mb-4">
        <div class="spinner-border text-primary" role="status"></div>
        <div class="spinner-border text-success" role="status"></div>
        <div class="spinner-border text-danger" role="status"></div>
        <div class="spinner-border text-warning" role="status"></div>
      </div>

      <!-- 2. Galería de Spinners Grow (Pulso) -->
      <div class="d-flex justify-content-center gap-3 mb-4">
        <div class="spinner-grow text-primary" role="status"></div>
        <div class="spinner-grow text-info" role="status"></div>
        <div class="spinner-grow text-dark" role="status"></div>
      </div>

      <!-- 3. Botón Interactivo con Estado de Carga -->
      <div>
        <button id="btnSincronizar" class="btn btn-primary px-4 py-2 rounded-pill fw-semibold shadow-sm" onclick="simularPeticion()">
          <span id="spinnerIcon" class="spinner-border spinner-border-sm d-none" aria-hidden="true"></span>
          <span id="btnText">Sincronizar con Kilopolis</span>
        </button>
      </div>
    </div>
  </div>

  <script>
    function simularPeticion() {
      const btn = document.getElementById('btnSincronizar');
      const spinner = document.getElementById('spinnerIcon');
      const txt = document.getElementById('btnText');

      // Activar estado de carga
      btn.disabled = true;
      spinner.classList.remove('d-none');
      txt.textContent = " Conectando al servidor...";

      // Simular retraso de red de 2 segundos
      setTimeout(() => {
        btn.disabled = false;
        spinner.classList.add('d-none');
        txt.textContent = "¡Sincronización Exitosa!";
        btn.classList.replace('btn-primary', 'btn-success');

        // Restaurar estado original tras 2.5 segundos
        setTimeout(() => {
          txt.textContent = "Sincronizar con Kilopolis";
          btn.classList.replace('btn-success', 'btn-primary');
        }, 2500);
      }, 2000);
    }
  </script>

</body>
</html>
Pruébalo tú mismo » Se abre en una nueva pestaña con ejecución en vivo
🦉
¿Tienes dudas con este tema?
Sócrates AI puede darte analogías y explicarte este código paso a paso.

🚀 ¿Quieres dominar Manual Completo de Bootstrap 5.3 y crear proyectos reales?

Aprende arquitectura limpia, desarrollo web moderno, buenas prácticas y despliegue en producción con nuestro Bootcamp Fullstack Developer con mentorías en vivo.

🏛️ Autoría y Propiedad Intelectual: Obra educativa original de David Amador para Kilopolis Academia (Solucionáticos), estructurada sobre las especificaciones y estándares abiertos del W3C, el estándar vivo de WHATWG y la documentación oficial de código abierto. © Todos los derechos reservados.