- La función CSS moderna scroll-snap convierte los elementos desplazables simples en carruseles paginados fluidos sin necesidad de JavaScript.
- Los nuevos pseudoelementos como ::scroll-button() y ::scroll-marker() generan controles de carrusel accesibles en CSS puro.
- Las estrategias basadas únicamente en CSS, combinadas con mecanismos de reserva cuidadosos y ARIA, ofrecen carruseles rápidos, resistentes e inclusivos.
- JavaScript se vuelve opcional, reservado para casos excepcionales como bucles infinitos reales o comportamientos complejos con estado.
Crear carruseles utilizando únicamente CSS moderno ya no es una utopía.—es una opción muy real y lista para producción que a menudo puede superar a las bibliotecas clásicas de deslizadores de JavaScript. Gracias a características como Ajuste de desplazamiento, animaciones controladas por desplazamiento, pseudoelementos de carrusel experimentales y primitivas de accesibilidad robustas.Puedes enviar carruseles ligeros y resistentes que, a la vez, ofrezcan una sensación suave, interactiva y pulida.
Si estás cansado de cargar paquetes de JavaScript de 50 KB solo para mostrar unas pocas diapositivasEsta guía te muestra lo que el CSS actual puede hacer por ti. Analizaremos los conceptos clave detrás de los carruseles solo con CSS, cómo conectarlos con scroll-snap, cuándo recurrir a las nuevas funciones. ::scroll-button() y ::scroll-marker() pseudoelementos y cómo incorporar la reproducción automática o el comportamiento circular sin dejar de tratar la accesibilidad y el rendimiento como elementos de primera clase.
Por qué los carruseles solo con CSS son finalmente una opción seria.
Durante años, "carrusel" fue casi sinónimo de "complemento de JavaScript".Las soluciones como Swiper, Glide o los controles deslizantes desarrollados internamente eran la opción preferida: gestionaban la navegación, el estado, la compatibilidad con el teclado y los gestos táctiles, pero a costa de un peso adicional, detectores de eventos por todas partes y una buena cantidad de manipulación del DOM.
El CSS moderno ha cerrado silenciosamente la mayor parte de esa brecha.. Con propiedades como scroll-snap-type y scroll-snap-align, puedes convertir cualquier desplazamiento horizontal o vertical en una experiencia paginada. Además de eso, la especificación CSS Overflow Nivel 5 introduce elementos generados por el navegador. botones de desplazamiento y marcadores que se comportan como una interfaz de usuario de carrusel completa, pero están declaradas íntegramente en CSS.
La gran ventaja es que el navegador, y no tu código JavaScript, se convierte en el responsable de los aspectos fundamentales de la experiencia de usuario.Desplazamiento físico, navegación por teclado, orden de enfoque e incluso funciones ARIA para los controles del carrusel. En muchos casos, resulta realmente difícil crear algo más accesible y con mejor rendimiento que lo que la plataforma ofrece de serie.
Otra gran ventaja de los carruseles CSS es la resiliencia.Si JavaScript no se carga correctamente, los usuarios con scripts bloqueados o deshabilitados seguirán viendo un conjunto de elementos desplazables perfectamente utilizables. No hay hidratación, ni cambios de diseño provocados por la carga tardía del código, y hay muchos menos elementos que puedan fallar con el tiempo.
Componente básico: un contenedor desplazable con Scroll Snap
Cada carrusel que solo utiliza CSS comienza su vida como un contenedor desplazable normal.Imagina una lista sencilla de diapositivas que se pueden desplazar horizontalmente. A partir de ahí, añades la función de ajuste automático al desplazamiento para que la ventana gráfica se fije automáticamente a cada diapositiva.
Una estructura HTML mínima para un carrusel horizontal es intencionalmente simple.: un elemento contenedor y una serie de elementos deslizantes en su interior. Podrías usar un ul con li elementos, o un div con niño divs—CSS se encarga del trabajo pesado, por lo que no necesita clases especiales para cada niño a menos que su diseño lo requiera.
Una configuración básica de ajuste al desplazamiento podría verse así en CSS., suponiendo una vista de ancho completo y de una sola diapositiva:
.carousel { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; }
.carousel-item { flex: 0 0 100%; scroll-snap-align: center; }
Aquí el contenedor utiliza display: flex alinear a sus hijos horizontalmente, y overflow-x: auto para habilitar el desplazamiento. La magia está en scroll-snap-type: x mandatory, que le indica al navegador que el desplazamiento horizontal siempre debe fijarse en un punto de anclaje válido, y en scroll-snap-align: center en cada diapositiva, que define esos puntos de anclaje.
Esta combinación de flexbox y scroll snap se siente instantáneamente como un carrusel.Los usuarios se desplazan o deslizan el dedo, y el deslizamiento más cercano se ajusta en su lugar. Debido a que aprovecha el desplazamiento nativo, la entrada táctil en teléfonos y tabletas simplemente funciona, sin ningún problema. manejadores de gestos o bibliotecas adicionales.
No está limitado a un solo artículo por vista.Para carruseles de varias columnas que muestran varias tarjetas a la vez, puede utilizar un ancho flexible para los elementos, por ejemplo:
.carousel-item { flex: 0 0 calc(33.333% - 1rem); margin: 0 0.5rem; scroll-snap-align: center; }
Esta variación permite mostrar, por ejemplo, tres tarjetas por ventana gráfica con un poco de espacio., sin dejar de beneficiarse del comportamiento de ajuste. Los usuarios se deslizan por páginas de tarjetas en lugar de diapositivas individuales, lo que funciona de maravilla para listas de productos o galerías.
Botones de desplazamiento con el pseudoelemento ::scroll-button()
Una vez que tienes un desplazamiento rápido, lo siguiente que la mayoría de la gente quiere son botones de navegación explícitos.—controles de anterior y siguiente que mueven el carrusel hacia la izquierda o hacia la derecha. Tradicionalmente, se crearía <button> elementos, vincular eventos de clic y calcular cuánto desplazarse.
La especificación CSS Overflow 5 introduce ::scroll-button(), un pseudoelemento que permite al navegador realizar todo ese trabajo pesado.Si bien esta función está disponible actualmente a partir de Chrome 135 (y normalmente solo se puede activar mediante opciones experimentales al principio), ofrece una idea de cómo se crearán los carruseles en el futuro.
Los botones de desplazamiento se declaran del mismo modo que cualquier otro pseudoelemento.Por ejemplo, para generar botones izquierdo y derecho para su carrusel:
.carousel::scroll-button(left) { content: "⬅" / "Scroll left"; }
.carousel::scroll-button(right) { content: "⮕" / "Scroll right"; }
.carousel::scroll-button(*) :focus-visible { outline-offset: 5px; }
Cuando se aplica este CSS, el navegador realmente crea un <button> elementos como hermanos del contenedor de desplazamientoLos conecta al carrusel, les asigna los roles apropiados y define su comportamiento. Un solo clic suele desplazar alrededor del 85 % del área de desplazamiento, lo que se asemeja a una "página" en la mayoría de los diseños de carrusel.
Si su diseño espera exactamente un elemento de ancho completo por clic, puedes combinar estos pseudo-elementos con un ajuste más estricto en cada hijo añadiendo scroll-snap-stop: alwaysEsto obliga a que la ventana gráfica se posicione en los límites de los elementos en lugar de detenerse a mitad de camino.
La propiedad del contenido en este caso cumple una doble función.: el primer valor es lo que los usuarios ven visualmente (en este caso, caracteres de flecha), y la segunda cadena es un texto alternativo accesible que puede exponerse a la tecnología de asistencia. Puede estilizar y posicionar estos botones con CSS o usar funciones como anchor() para alinearlos con precisión con su diseño.
Marcadores de desplazamiento con ::scroll-marker() y ::scroll-marker-group
Los puntos o etiquetas debajo de un carrusel, a menudo llamados "puntos de paginación" o "marcadores", son otro requisito común.Muestran cuántos elementos existen y cuál está visible en ese momento, y permiten a los usuarios saltar directamente a una diapositiva específica.
El ::scroll-marker() El pseudo-elemento te proporciona estos indicadores sin generar manualmente enlaces de anclaje o spans.Cada marcador es esencialmente una navegación <a> Elemento creado por el navegador, que apunta al elemento de desplazamiento correspondiente y participa en la navegación mediante teclado y lector de pantalla.
Para configurar esto, debes indicarle al navegador dónde colocar el grupo de marcadores. con scroll-marker-groupy sobre qué elementos crear marcadores. Una configuración mínima podría ser la siguiente:
.carousel { scroll-marker-group: after; }
.carousel > li::scroll-marker { content: " "; }
.carousel > li::scroll-marker:target-current { background: var(--accent); }
El navegador construye un ::scroll-marker-group El contenedor es un elemento hermano del desplazamiento y lo llena con un marcador para cada elemento hijo seleccionado.En este sencillo ejemplo, los marcadores se representan como puntos vacíos, pero también puede usar fácilmente texto como "Temporada 1", iconos o incluso miniaturas cambiando el content propiedad.
¿Qué hace que estos marcadores sean especiales en comparación con una barra de desplazamiento simple? es que son enlaces de navegación reales. Permiten a los usuarios saltar directamente a posiciones significativas y vienen con una semántica útil: hay un :target-current Estado que indica qué marcador corresponde a la diapositiva actualmente visible o ajustada. La compatibilidad con el teclado funciona como un grupo focal, y los lectores de pantalla pueden mostrarlos como un control similar a una lista de pestañas.
Esta estrategia es especialmente eficaz cuando el desplazamiento representa bloques lógicos en lugar de elementos individuales.Por ejemplo, en lugar de crear diez marcadores para diez episodios, podrías crear dos marcadores que te lleven directamente al inicio de la primera y la segunda temporada. Puedes decidir qué "puntos de interés" se pueden incluir.
Combinación de botones y marcadores en una interfaz de usuario de carrusel completa.
Cuando pones ::scroll-button() y ::scroll-marker() juntos en el mismo desplazamientoEl resultado es una interfaz de usuario que los usuarios reconocen al instante como un carrusel: controles de anterior/siguiente, una fila de marcadores que muestran el avance y un ajuste fluido entre las diapositivas.
La principal diferencia con los deslizadores JavaScript clásicos es que la mayor parte de esta lógica ahora reside en el navegador.Los botones y marcadores son elementos generados con roles ARIA correctos, integrados adecuadamente en el orden de tabulación y con una historia de accesibilidad diseñada por los equipos del navegador subyacente, en lugar de reinventarse para cada sitio.
Este enfoque aporta varios beneficios muy prácticos.Funciona con JavaScript deshabilitado, elimina el parpadeo de hidratación y los problemas de sincronización, reduce el desplazamiento acumulativo del diseño porque los controles se conocen en el momento del diseño CSS y se integra a la perfección con animaciones controladas por desplazamiento o consultas de estado de desplazamiento si se desea añadir un toque especial.
En dispositivos táctiles, la experiencia es naturalmente amigable con los dedos. porque el contenedor de desplazamiento sigue siendo simplemente un control de desplazamiento nativo. En ordenadores de escritorio, la rueda del ratón y la entrada de teclado funcionan como se espera, y los indicadores de enfoque en los controles generados se pueden personalizar para que cumplan con las directrices de diseño y accesibilidad.
Desde la perspectiva del mantenimiento, "hacer menos, lograr más" se convierte en una descripción bastante precisa.En lugar de mantener la lógica de múltiples implementaciones de carrusel en distintos proyectos, te apoyas en funciones de plataforma compartidas y estandarizadas que seguirán mejorando con el tiempo sin que tengas que hacer ningún trabajo adicional.
Cómo hacer que Scroll Snap funcione en proyectos reales
Incluso si ignoramos los nuevos pseudoelementos por un momento, la función scroll-snap por sí sola ya es suficiente para muchos carruseles de producción.La compatibilidad de los navegadores con la función scroll-snap en los motores modernos es sólida, y el comportamiento es predecible tanto con la rueda del ratón como con los gestos táctiles.
En el escenario más simple, su carrusel HTML podría ser un div con una serie de imágenes en el interior. Puedes darle a ese contenedor una clase como .carousel y deja las imágenes secundarias sin clasificar; CSS se encarga de la alineación y el desplazamiento.
al encender scroll-behavior: smooth en el contenedorEl desplazamiento entre los puntos de anclaje se vuelve fluido y dinámico en lugar de brusco. Esto se nota especialmente cuando los usuarios hacen clic en marcadores o enlaces de anclaje, o cuando se activa el desplazamiento mediante programación en configuraciones híbridas.
Cada propiedad clave de scroll-snap desempeña un papel muy distinto.. scroll-snap-type define el eje y si el ajuste es obligatorio o solo una sugerencia; scroll-snap-align en los niños especifica dónde se fijan en la vista (inicio, centro, final); y scroll-snap-stop: always Evita que el navegador omita los puntos de anclaje al desplazarse rápidamente.
Utilizadas en conjunto, estas propiedades te permiten ajustar con precisión cómo debe sentirse el carrusel.—desde un ajuste suave y permisivo, adecuado para secciones de contenido extensas, hasta un comportamiento estricto, de deslizamiento por deslizamiento, perfecto para banners principales donde nunca se desea aterrizar "entre" elementos.
Como se trata de CSS puro, puedes adaptar fácilmente el diseño de forma responsiva.. Con las consultas de medios, cambie de una diapositiva por vista en pantallas estrechas a varias por vista en ordenadores de escritorio anchos, simplemente cambiando el flex-basis de elementos. No se requieren puntos de interrupción de JavaScript, detectores de redimensionamiento ni anchos recalculados.
Pseudoelementos experimentales y detección de características
Los nuevos pseudoelementos orientados al carrusel—::scroll-button(), ::scroll-marker() y ::scroll-marker-group—son potentes pero aún relativamente nuevosEn el momento de escribir este artículo, están disponibles en Chrome 135 y versiones posteriores, a menudo con la necesidad de activar ciertas opciones experimentales, y se irán implementando en otros motores con el tiempo.
Dado que la compatibilidad aún no es universal, los sitios de producción deben basarse en la detección de características y en mecanismos de reserva adecuados.. CSS te da el @supports La regla `at` permite aplicar reglas de forma condicional en función del reconocimiento de propiedades.
Podrías definir una sencilla barra de navegación alternativa.—un conjunto de enlaces o botones que se encuentran debajo del carrusel— y luego ocultan esa franja cuando el navegador admite botones de desplazamiento nativos. Por ejemplo:
.carousel-nav { display: flex; gap: 0.5rem; }
@supports (scroll-button-inline: both) { .carousel-nav { display: none; } }
Aquí .carousel-nav puede contener enlaces de anclaje creados manualmente que apuntan a diapositivas mediante identificadores.del ADN, tales como los <a href="#slide1">1</a>En los navegadores que reconocen la nueva propiedad scroll-button, aparecen los controles nativos y se oculta la navegación alternativa; en los navegadores más antiguos, la navegación con anclajes permanece, junto con scroll-snap para una experiencia perfectamente utilizable.
Esta estrategia híbrida permite experimentar con seguridad con las funciones de carrusel de próxima generación en la actualidad.Sin limitarse a una configuración de motor o de banderas específica. A medida que la compatibilidad con los navegadores mejore, podrá apoyarse más en los pseudoelementos y reducir parte del andamiaje manual.
Carruseles de reproducción automática solo con CSS y animaciones por fotogramas clave
Otra solicitud común es la reproducción automática: un carrusel que avanza por sí solo y que, opcionalmente, se pausa al pasar el cursor por encima.Si bien la reproducción automática conlleva algunas limitaciones en cuanto a la experiencia de usuario y la accesibilidad, es posible lograrla únicamente con animaciones CSS.
Un patrón sencillo consiste en animar la traslación horizontal de la pista de diapositivas..
@keyframes slide {
0%, 20% { transform: translateX(0); }
25%, 45% { transform: translateX(-100%); }
50%, 70% { transform: translateX(-200%); }
75%, 95% { transform: translateX(-300%); }
100% { transform: translateX(0); }
}
.autoplay-carousel { display: flex; animation: slide 12s infinite; }
.autoplay-carousel:hover { animation-play-state: paused; }
En este ejemplo, los fotogramas clave permanecen en intervalos de tiempo en cada desplazamiento antes de pasar a la siguiente diapositiva.La pista se repite al final, dando la apariencia de una presentación de diapositivas repetitiva de cuatro diapositivas. Al pasar el cursor sobre el carrusel, la animación se pausa, lo que permite a los usuarios inspeccionar el contenido sin tener que lidiar con el movimiento constante.
Para respetar a los usuarios que prefieren reducir el movimiento por motivos de salud o comodidad.Puedes envolver la animación en una consulta de medios:
@media (prefers-reduced-motion: reduce) { .autoplay-carousel { animation: none; } }
Esto garantiza que en los sistemas donde se requiere un movimiento reducido, los toboganes permanezcan estáticos., desactivando efectivamente la reproducción automática, pero permitiendo al mismo tiempo el desplazamiento manual o la navegación mediante botones/marcadores cuando estén disponibles.
Una desventaja importante es que la reproducción automática basada en fotogramas clave no se integra automáticamente con el ajuste al desplazamiento.Como estás traduciendo el contenido manualmente en lugar de usar el desplazamiento nativo, debes diseñar la animación con cuidado para evitar diapositivas parcialmente visibles y mantener la sincronización con tu diseño.
Consideraciones de accesibilidad para carruseles CSS
La accesibilidad es un área donde los carruseles basados en CSS pueden brillar de verdad.Porque gran parte de la lógica compleja se traslada de tu código personalizado a comportamientos de la plataforma que han sido cuidadosamente diseñados y probados.
Cuando utilizas el desplazamiento nativo más la función de ajuste al desplazamiento, heredas automáticamente la compatibilidad con teclado, pantalla táctil y ratón.Los usuarios pueden acceder al desplazamiento mediante la tecla Tab, usar las teclas de flecha para moverse, deslizar el dedo en pantallas táctiles y desplazarse con una rueda, sin necesidad de detectores de eventos ni controladores personalizados.
Los botones de desplazamiento y marcadores experimentales van un paso más allá.El navegador los crea con la semántica adecuada, los integra en el orden de tabulación y mantiene su estado, lo que dificulta enormemente olvidar accidentalmente los atributos ARIA o etiquetarlos incorrectamente. Los controles de carrusel resultantes tienden a ser más accesibles de forma consistente que las implementaciones personalizadas.
Aún puedes y debes agregar sugerencias semánticas a las regiones de tu carrusel.. Por ejemplo, marcando el contenedor con role="region" y una descriptiva aria-label Ayuda a los usuarios de lectores de pantalla a comprender qué representa el componente:
<div class="carousel" role="region" aria-label="Product gallery">
<div class="carousel-item" aria-label="Slide 1 of 3">...</div>
</div>
Garantizar indicadores de enfoque visibles para todos los elementos interactivos sigue siendo fundamental.Ya sean botones y enlaces propios o pseudoelementos generados por el navegador, asegúrese de que los contornos de enfoque no se eliminen o se hagan demasiado sutiles para verlos. Ajustar outline, outline-offset o realizar cambios de fondo según sea necesario para cumplir con los requisitos de contraste.
El tamaño del objetivo táctil es otra consideración práctica.Procure que los controles tengan un tamaño mínimo de 44×44 píxeles para cumplir con las directrices de accesibilidad habituales, de modo que los usuarios no tengan dificultades para pulsar las flechas o los puntos en pantallas más pequeñas.
Para cualquier función de reproducción automática, proporcione a los usuarios un control claro y evite movimientos demasiado bruscos.. Proporcione una pausa al pasar el cursor o un botón de pausa explícito, y considere desactivar la reproducción automática por defecto si el contenido es denso o tiene mucho texto. Combinado con prefers-reduced-motionEsto hace que tu carrusel sea más cómodo para un público más amplio.
Cómo gestionar el desplazamiento circular o “infinito” con CSS
Una de las funciones que la gente suele pedir es el desplazamiento circular.Cuando llegas a la última diapositiva y sigues desplazándote, vuelves suavemente a la primera, como un carrusel físico que gira sin cesar.
Actualmente, no existe ninguna propiedad CSS directa que haga que un contenedor de desplazamiento sea inherentemente circular.Sin duplicar contenido, un desplazamiento nativo tendrá un principio y un final: una vez que llegues al último elemento, seguir desplazándote simplemente no te hará avanzar.
Los autores de las especificaciones son conscientes de que muchos carruseles de interfaz de usuario esperan este comportamiento de bucle.Existe un gran interés en explorar soluciones a nivel de plataforma para el desplazamiento cíclico, de forma similar a como se estandarizaron los nuevos botones y marcadores de desplazamiento. Dicho esto, por el momento no es posible solicitar a un navegador que ajuste las posiciones de desplazamiento de forma nativa con una sola declaración CSS.
En configuraciones puramente CSS, simular bucles generalmente significa animar transformaciones (como en los ejemplos de fotogramas clave de reproducción automática) o aceptar un final lineal para la secuencia.Si se requiere absolutamente una continuidad perfecta y no se puede duplicar el contenido, JavaScript sigue siendo la herramienta más flexible por el momento.
La buena noticia es que nada te impide combinar un carrusel basado principalmente en CSS con un poco de JavaScript donde realmente aporte valor.Podrías usar scroll-snap y botones CSS para la navegación diaria, y luego agregar unas pocas líneas de código para monitorear la posición de desplazamiento y saltar del final al principio cuando sea apropiado.
HTML/CSS frente a JavaScript para carruseles enriquecidos basados en tarjetas.
Un dilema frecuente para los desarrolladores novatos es si un carrusel de tarjetas más complejo "debe" escribirse en JavaScript.La gente suele pensar que en cuanto se va más allá de las imágenes simples y se pasa a las tarjetas responsivas con varios componentes, el CSS por sí solo deja de ser viable.
En la práctica, la función CSS scroll-snap funciona igual de bien para tarjetas con contenido enriquecido que para imágenes simples.Siempre que cada tarjeta sea un bloque dentro del contenedor de desplazamiento, puedes ajustarla, animarla a su alrededor y superponer estilos adicionales. Los títulos, botones, fragmentos de texto e incluso los elementos multimedia incrustados no alteran fundamentalmente la mecánica.
Donde JavaScript brilla es en el comportamiento condicional y el estado complejo.Si tu carrusel debe filtrar tarjetas dinámicamente, reordenar diapositivas, sincronizarse con otros componentes, obtener contenido nuevo sobre la marcha o admitir lógica altamente personalizada ("si se hace clic en este punto, mostrar esa tarjeta totalmente ajena"), entonces JavaScript puede expresar esa lógica de negocio más fácilmente que solo CSS.
Sin embargo, una cantidad sorprendente de controles deslizantes cotidianos son esencialmente listas estáticas de elementos que avanzan linealmente.En esos casos, usar unas pocas líneas de CSS en lugar de importar una gran biblioteca de JavaScript es más sencillo de entender y ofrece un mejor rendimiento. Comprender el ajuste automático al desplazamiento (scroll-snap) y los nuevos pseudoelementos permite reservar JavaScript para los casos excepcionales en los que realmente resulta rentable.
Si todavía estás aprendiendo desarrollo front-end, tratar los carruseles CSS como tu base predeterminada es un gran hábito.Empieza con HTML y CSS, y recurre a scripts solo cuando encuentres una limitación clara. Esto te permitirá conocer mejor las capacidades de la plataforma y, a menudo, dará como resultado bases de código más sencillas y limpias.
Retrocediendo un poco, el conjunto emergente de características CSS en torno al desplazamiento, el ajuste, los botones, los marcadores y las consultas de estado de desplazamiento. ha transformado los carruseles de widgets con mucho código en componentes mayoritariamente declarativos. Al apoyarse en scroll-snap para el comportamiento de paginación principal, utilizando ::scroll-button() y ::scroll-marker() Cuando sea compatible y se apliquen las mejores prácticas de detección de funciones y accesibilidad, se pueden implementar carruseles rápidos, robustos y más fáciles de mantener que los deslizadores tradicionales basados en JavaScript, manteniendo al mismo tiempo la suficiente flexibilidad para incorporar JavaScript cuando la lógica cíclica o las interacciones avanzadas realmente lo requieran.