Desarrollo Frontend

Cómo crear un Carrusel Infinito y Responsive solo con HTML y CSS

learn.carouselOnlyHtmlCss.Header.subtitle

Aprende a maquetar un slider de imágenes automático con animaciones fluidas, variables CSS y diseño adaptativo, sin escribir una sola línea de JavaScript.

Estructura HTML: El Escenario y la Pista

Construimos la base. Tenemos un contenedor principal (.carousel) que actúa como 'ventana', y dentro, una 'pista' (.carousel-inner) que contiene todos los slides. Esta pista es la que moveremos horizontalmente para crear el efecto de desplazamiento.

Copiar con comentariosCopiado
Copiar sin comentariosCopiado
<div class="carousel">
  

  <div class="carousel-inner">
    

    
    <div class="carousel-item">
      <img src="..." class="carousel-image" alt="playa" />
      <div class="carousel-caption">
        <h2 class="carousel-title">Playa rocosa</h2>
        <p class="carousel-text">Descubrí una costa única...</p>
        <button class="carousel-button">Ver más</button>
      </div>
    </div>

    
    <div class="carousel-item">...</div>
    <div class="carousel-item">...</div>

  </div>
</div>
Diagrama de arquitectura del carrusel: Contenedor vs Pista vs Items
Esquema de la arquitectura: el contenedor padre (.carousel) actúa como una máscara fija, mientras el hijo (.carousel-inner) es la pista que se desplaza.
Copiar con comentariosCopiado
Copiar sin comentariosCopiado
<div class="carousel">
  

  <div class="carousel-inner">
    

    
    <div class="carousel-item">
      <img src="..." class="carousel-image" alt="playa" />
      <div class="carousel-caption">
        <h2 class="carousel-title">Playa rocosa</h2>
        <p class="carousel-text">Descubrí una costa única...</p>
        <button class="carousel-button">Ver más</button>
      </div>
    </div>

    
    <div class="carousel-item">...</div>
    <div class="carousel-item">...</div>

  </div>
</div>

CSS: Variables y el Contenedor Principal

Definimos variables CSS para controlar fácilmente la cantidad de slides y la altura. El contenedor principal usa `overflow: hidden` para ocultar todo lo que esté fuera de la 'ventana' visible, creando el efecto de máscara.

Copiar con comentariosCopiado
Copiar sin comentariosCopiado
/* Reset básico (mejor que el selector universal)
- Evita que el navegador agregue márgenes/padding por defecto.
- Lo aplicamos solo a html y body para no “romper” estilos internos de otros elementos (como inputs, botones, etc.).*/

 html, body {
   margin: 0;
   padding: 0;
}

 .carousel {
   /* Variables para fácil configuración */
  --slides: 3;       /* Cantidad total de slides */
  --h: 35dvw;        /* Altura proporcional al ancho del viewport */

  width: 100%;
  height: var(--h);
  overflow: hidden;  /* La magia: oculta los slides que no están en foco */
}

La Pista Animada (Flexbox y Cálculos)

El `.carousel-inner` es donde ocurre la acción. Usamos `display: flex` para poner los slides en fila y `calc()` para definir el ancho total basado en la cantidad de slides (3 slides = 300% de ancho) . Aquí vinculamos la animación 'slide'.

Copiar con comentariosCopiado
Copiar sin comentariosCopiado
.carousel-inner {
  display: flex;             /* Alinea los slides horizontalmente */
  height: 100%;
  
  /* Ancho dinámico: Si son 3 slides, ancho = 300% */
  width: calc(var(--slides) * 100%);

  /* La animación que mueve la pista */
  animation: slide 20s infinite ease-in-out;
  will-change: transform;    /* Optimización de rendimiento */
}

.carousel-item {
  position: relative;
  /* Cada slide ocupa exactamente una fracción del ancho total (100% / 3) */
  flex: 0 0 calc(100% / var(--slides));
  height: 100%;
  display: flex;
  place-content: center;
  place-items: center;
}
Visualización de cómo object-fit recorta la imagen para llenar el contenedor
Demostración de 'object-fit: cover': la imagen escala para llenar el contenedor y recorta los bordes sobrantes automáticamente para no distorsionarse.
Copiar con comentariosCopiado
Copiar sin comentariosCopiado
.carousel-image {
  position: absolute;
  inset: 0;           /* Top, Right, Bottom, Left en 0 */
  width: 100%;
  height: 100%;
  
  object-fit: cover;  /* Recorta la imagen para llenar el contenedor */
  z-index: 1;         /* Queda por detrás del texto */
}

Estilizando el Contenido (Caption)

El texto va sobre la imagen. Usamos un fondo semitransparente con `rgb(0 0 0 / 0.5)` para garantizar legibilidad y unidades relativas (`dvw`) para que el tamaño del texto y los botones escale perfectamente con la pantalla.

Copiar con comentariosCopiado
Copiar sin comentariosCopiado
.carousel-caption {
  position: relative;
  z-index: 2;                  /* Por encima de la imagen */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  
  width: 40dvw;                /* Ancho relativo al viewport */
  padding: 5dvw;
  gap: 3dvw;
  border-radius: 2dvw;
  
  background: rgb(0 0 0 / 0.5); /* Fondo oscuro semitransparente */
  color: #fff;
  text-align: center;
}

.carousel-title {
  font-size: 1.6dvw;           /* Tipografía responsiva */
  font-weight: 700;
}

.carousel-text {
  /* Texto un poco más chico */
  font-size: 1dvw;
}
Publicidad
htmlCssOnlineCourseResponsiveWebDesignFromScratch

Aprendé desde cero con clases 100% en vivo, grupos súper reducidos y acompañamiento real. Todo el contenido está diseñado y dictado por el creador de la plataforma, para que aprendas de verdad, sin videos fríos ni cursos masivos.

Curso de HTML y CSS para Frontend

Dominá las bases de la programación frontend: estructura con HTML, estilos modernos con CSS y diseño rápido con Tailwind para lanzar tus primeros sitios responsivos y profesionales.10 clases en vivo con profesores expertos
Precio $150000 ARG Oferta especialDisponible por 0 Días y 00:00:00 Hs
Ver próximas fechas

La Lógica de la Animación (Keyframes)

Aquí está el cerebro del carrusel. Usamos porcentajes negativos de `translateX` para mover la pista. Lo importante son las pausas: notarás que hay rangos (ej: 0% a 22.5%) donde el valor no cambia, esto permite que el slide se quede quieto para que el usuario pueda leerlo.

Copiar con comentariosCopiado
Copiar sin comentariosCopiado
@keyframes slide {
  /* Slide 1: Quieto del 0% al 22.5% */
  0%, 22.5%     { transform: translateX(0%); }

  /* Slide 2: Quieto del 25% al 47.5% (-33.33% es 1/3 del ancho) */
  25%, 47.5%    { transform: translateX(-33.333%); }

  /* Slide 3: Quieto del 50% al 72.5% (-66.66% es 2/3 del ancho) */
  50%, 72.5%    { transform: translateX(-66.666%); }

  /* Vuelta al Slide 2 (efecto rebote o ciclo) */
  75%, 97.5%    { transform: translateX(-33.333%); }

  /* Vuelta al inicio */
  100%          { transform: translateX(0%); }
}
Copiar con comentariosCopiado
Copiar sin comentariosCopiado
@keyframes slide {
  /* Slide 1: Quieto del 0% al 22.5% */
  0%, 22.5%     { transform: translateX(0%); }

  /* Slide 2: Quieto del 25% al 47.5% (-33.33% es 1/3 del ancho) */
  25%, 47.5%    { transform: translateX(-33.333%); }

  /* Slide 3: Quieto del 50% al 72.5% (-66.66% es 2/3 del ancho) */
  50%, 72.5%    { transform: translateX(-66.666%); }

  /* Vuelta al Slide 2 (efecto rebote o ciclo) */
  75%, 97.5%    { transform: translateX(-33.333%); }

  /* Vuelta al inicio */
  100%          { transform: translateX(0%); }
}
Gráfico de línea de tiempo de los Keyframes mostrando pausas y movimientos
Representación gráfica de la línea de tiempo: las 'mesetas' indican las pausas de lectura y las pendientes representan el movimiento de transición.

Responsive: Adaptación a Móviles Verticales

Utilizamos la media query `orientation: portrait` para detectar si el dispositivo está en vertical (como un celular). Ajustamos la altura (`--h`) para que sea más alto y redefinimos los tamaños de fuente y padding para que sean legibles en pantallas estrechas.

Copiar con comentariosCopiado
Copiar sin comentariosCopiado
@media (orientation: portrait) {
  .carousel {
    /* En vertical usamos el 65% de la altura de la pantalla */
    --h: 65dvh;
  }

  .carousel-caption {
    /* Ancho casi total y texto más grande */
    width: 70%;
    padding: 6dvw;
    gap: 4dvw;
    border-radius: 4dvw;
  }

  .carousel-title { font-size: 5dvw; }
  .carousel-text  { font-size: 3.2dvw; }

  .carousel-button {
    width: 70%;
    padding: 3.2dvw;
    font-size: 3.4dvw;
  }
}

Resultado Final: Desktop vs Mobile

El resultado es un componente robusto que mantiene la relación de aspecto cinematográfica en escritorio y cambia a un formato de 'historia' vertical en móviles, todo controlado por CSS moderno.

¿Es realmente posible hacer un carrusel sin JavaScript?Sí. Utilizando animaciones CSS (`@keyframes`) y transformaciones (`translateX`), podemos mover los elementos automáticamente en un bucle infinito sin necesidad de scripts.
¿Cuál es la ventaja de no usar JavaScript para un slider?El rendimiento es mucho mejor porque la animación corre en el hilo del compositor del navegador (GPU), no bloquea el renderizado y funciona incluso si el usuario tiene JS desactivado.
¿Para qué sirve la variable `--slides` en el CSS?Es una variable personalizada (Custom Property) que define cuántas diapositivas tiene el carrusel. Se usa en `calc()` para determinar el ancho total de la pista automáticamente.
¿Por qué el contenedor `.carousel` tiene `overflow: hidden`?Actúa como una máscara o ventana. Oculta todo el contenido que se sale de sus bordes, permitiendo que solo veamos el slide actual mientras los demás esperan a los lados.
¿Qué hace exactamente `width: calc(var(--slides) * 100%)`?Calcula el ancho de la pista interna. Si tienes 3 slides, el ancho será 300%. Esto es necesario para que los slides se coloquen uno al lado del otro horizontalmente.
¿Por qué usamos `display: flex` en `.carousel-inner`?Flexbox coloca automáticamente los hijos directos (`.carousel-item`) en una fila horizontal, creando la estructura de tira larga necesaria para el deslizamiento.
¿Qué significa la unidad `dvw` utilizada en el código?`dvw` (Dynamic Viewport Width) es una unidad relativa al ancho de la pantalla que tiene en cuenta las barras de herramientas dinámicas de los navegadores móviles, evitando saltos de tamaño.
¿Cómo funcionan los porcentajes en `@keyframes slide`?Los porcentajes indican el momento de la animación. Por ejemplo, `0%` es el inicio y `100%` el final. Los intervalos intermedios definen cuándo mover la pista y cuándo pausarla.
¿Por qué hay rangos repetidos en los keyframes (ej: `0%, 22.5%`)?Esos rangos crean las pausas. Al mantener el mismo valor de `transform` durante un periodo (del 0 al 22.5%), el carrusel se queda quieto para que el usuario pueda ver la imagen.
¿Por qué usamos valores negativos en `translateX`?Porque para mostrar el siguiente slide (que está a la derecha), necesitamos mover toda la pista hacia la izquierda. `translateX(-33.33%)` mueve la pista un tercio hacia la izquierda.
¿Qué función cumple `object-fit: cover` en las imágenes?Asegura que la imagen cubra todo el contenedor sin deformarse, recortando los excesos si es necesario. Es fundamental para mantener la estética en diferentes tamaños de pantalla.
¿Para qué sirve `will-change: transform`?Es una optimización que avisa al navegador que esa propiedad va a cambiar, permitiéndole preparar recursos (como capas de la GPU) para que la animación sea más fluida.
¿Cómo puedo añadir más slides al carrusel?Debes añadir el HTML del nuevo slide, actualizar la variable `--slides` a 4 (o el número que sea) y recalcular los porcentajes en los `@keyframes` para dividir el tiempo correctamente.
¿Por qué usamos `position: absolute` en la imagen?Para sacarla del flujo normal y permitir que el texto (`.carousel-caption`) se posicione encima de ella fácilmente usando `z-index`.
¿Qué es `inset: 0`?Es una forma abreviada moderna de escribir `top: 0; right: 0; bottom: 0; left: 0;`. Hace que el elemento absoluto ocupe todo el tamaño de su padre relativo.
¿Cómo detengo el carrusel cuando paso el mouse por encima?Puedes añadir `.carousel-inner:hover { animation-play-state: paused; }`. Esto congelará la animación mientras el cursor esté sobre el carrusel.
¿Por qué usar `place-items: center`?Es una propiedad shorthand de Grid y Flexbox que centra el contenido tanto vertical como horizontalmente en una sola línea de código.
¿Qué hace la media query `@media (orientation: portrait)`?Detecta si el dispositivo está en posición vertical (altura mayor que anchura), ideal para aplicar estilos específicos para teléfonos móviles sin depender de un ancho en píxeles exacto.
¿Puedo poner videos en lugar de imágenes?Sí. Solo reemplaza la etiqueta `<img>` por una etiqueta `<video>` con las propiedades `autoplay`, `loop`, `muted` y la clase `.carousel-image` para mantener los estilos.
¿Cómo calculo los porcentajes de `translateX` si tengo 4 slides?El desplazamiento sería en incrementos de 25% (100% / 4). Sería: 0%, -25%, -50%, -75%.
¿Es responsive el texto dentro del carrusel?Sí, al usar unidades `dvw` (viewport width) para `font-size`, `padding` y `gap`, el contenido escala proporcionalmente al ancho de la pantalla.
¿Por qué se usa `z-index: 1` en la imagen y `2` en el texto?El sistema de apilamiento (stacking context) requiere que el texto tenga un índice mayor para aparecer visualmente encima de la imagen de fondo.
¿Cómo afecta al SEO este tipo de carrusel?Generalmente bien, ya que el contenido está en el HTML y es legible por los bots. Sin embargo, asegúrate de usar atributos `alt` descriptivos en las imágenes.
¿Puedo agregar botones de 'Siguiente' y 'Anterior'?Con CSS puro es difícil controlar la animación en curso. Para botones funcionales que cambien el slide a demanda, se recomienda usar el 'Radio Button Hack' o JavaScript.
¿Qué pasa si las imágenes tienen diferentes tamaños?Gracias a `object-fit: cover` y a que el contenedor padre define la altura, todas las imágenes se forzarán a llenar el espacio uniformemente, ocultando las diferencias.
¿Por qué usamos `rgb(0 0 0 / 0.5)` en el caption?Es la sintaxis moderna de CSS para colores con transparencia (alpha). Crea un fondo negro al 50% de opacidad para mejorar la legibilidad del texto blanco sobre fotos.
¿Puedo cambiar la dirección del carrusel (de izquierda a derecha)?Sí, invirtiendo los valores de `translateX` a positivos, aunque necesitarías ajustar la posición inicial del flex-container para que empiece desde el final.
¿Es compatible `dvw` con todos los navegadores?Tiene muy buen soporte en navegadores modernos. Para navegadores muy antiguos, podrías necesitar un fallback usando `vw` o `%`.
¿Cómo evito el 'salto' brusco al final de la animación?El último keyframe suele devolver el carrusel al inicio o duplicar el primer slide al final (técnica de clonación) para simular un bucle infinito perfecto.
¿Por qué definimos `--h` como variable?Para mantener la consistencia. Si queremos cambiar la altura del carrusel, solo modificamos esa variable en una línea y se actualiza en todo el componente.
¿Qué diferencia hay entre `ease-in-out` y `linear`?`linear` es una velocidad constante. `ease-in-out` acelera al principio y frena al final del movimiento, haciendo que el deslizamiento se sienta más natural y suave.
¿Cómo hago que el carrusel vaya más rápido o más lento?Modificando la duración de la animación. En `animation: slide 20s...`, cambia `20s` por un valor menor (más rápido) o mayor (más lento).
¿Puedo usar gradientes sobre las imágenes?Sí, puedes añadir un pseudo-elemento `::after` con un `linear-gradient` sobre el `.carousel-item` para oscurecer la imagen y mejorar el contraste del texto.
¿Es accesible este carrusel para lectores de pantalla?El cambio automático puede ser problemático. Lo ideal es proveer un mecanismo de pausa y asegurar que el atributo `alt` sea descriptivo. `aria-live` puede ser necesario para anunciar cambios.
¿Por qué usamos `flex: 0 0 calc(100% / var(--slides))`?`flex-grow: 0` y `flex-shrink: 0` aseguran que el slide no cambie de tamaño. El ancho calculado garantiza que cada slide ocupe exactamente una fracción igual del contenedor.
¿Se puede hacer un carrusel vertical con esta técnica?Sí, cambiando `flex-direction: column` y animando `translateY` en lugar de `translateX`. También habría que ajustar el cálculo de las alturas.
¿Cómo depurar si la animación se ve extraña?Usa las herramientas de desarrollo de Chrome/Firefox. Puedes reducir la velocidad de las animaciones al 10% en la pestaña 'Animations' para ver exactamente qué ocurre en cada frame.
¿Qué pasa si tengo contenido de texto muy largo?Si el texto excede la altura del slide, se cortará debido al `overflow: hidden` del padre. Deberías usar `clamp()` en las fuentes o limitar la cantidad de caracteres.
¿Es necesario usar prefijos `-webkit-` hoy en día?Para propiedades estándar como `transform` y `animation`, ya no es estrictamente necesario en navegadores modernos, pero herramientas como Autoprefixer pueden agregarlos por seguridad.
¿Cómo logro que el texto aparezca con un efecto de 'fade in'?Puedes añadir una animación separada al `.carousel-caption` (ej: cambios de opacidad) que esté sincronizada con los tiempos de la animación principal del slider.
¿Por qué reseteamos `html` y `body` con margin 0?Los navegadores aplican un margen por defecto de 8px al body. Si no lo quitamos, el carrusel de ancho completo (`width: 100%`) generará una barra de scroll horizontal indeseada.
¿Se puede usar `grid` en lugar de `flex` para la pista?Sí, `display: grid` con `grid-template-columns` también funcionaría, pero Flexbox suele ser más intuitivo para alineaciones unidimensionales (una sola fila).
¿Qué es la propiedad `isolation` o stacking context?A veces necesaria si los z-index no funcionan como esperas. Crear un contexto de apilamiento asegura que los elementos hijos se ordenen correctamente entre sí.
¿Cómo hacer que el carrusel ocupe toda la pantalla (Fullscreen)?Cambia la variable `--h` a `100dvh` (100% de la altura dinámica del viewport). Así el carrusel cubrirá todo el dispositivo.
¿El uso de `calc()` afecta el rendimiento?Es insignificante. Los navegadores modernos optimizan `calc()` muy bien. El impacto real en rendimiento suele venir de animar propiedades pesadas como `width` o `margin` en lugar de `transform`.
¿Cómo añado indicadores (puntos) de la diapositiva actual?Solo con CSS y animación automática es complejo sincronizarlos visualmente. Se requeriría otra animación paralela para los puntos o usar el 'Radio Hack'.
¿Qué pasa si desactivo el `overflow: hidden`?Verías todos los slides extendiéndose hacia la derecha de la pantalla, generando una barra de desplazamiento horizontal enorme en la página.
¿Por qué usar `border-radius` en unidades `dvw`?Para mantener la curvatura de las esquinas proporcional al tamaño del carrusel. Si usaras `px` fijos, las esquinas se verían muy pequeñas en pantallas grandes o muy grandes en móviles.
¿Puedo usar imágenes SVG?Sí, los SVGs son excelentes por su escalabilidad. Funcionan igual que JPG o PNG dentro de la etiqueta `<img>` y con `object-fit`.
¿Dónde es mejor colocar este CSS?En un archivo externo (ej: `carousel.css`) linkeado en el head. Esto permite que el navegador cachee los estilos y mantiene tu HTML limpio.

Información de cursos

Completá el formulario y recibí detalles sobre contenidos, fechas, niveles y promociones disponibles.

Completá el formulario para mantenerte informado. 👉