Muchas veces, cuando estamos diseñando una web, necesitamos apilar de manera horizontal una serie de tarjetas o contenedores y permitir que el usuario los desplace de izquierda a derecha. Aunque no se limita solo a contenedores: puede que quieras que toda tu web tenga una navegación horizontal, lo que se conoce como un sitio horizontal.
La web es, por naturaleza, vertical. Sin embargo, hay muchos escenarios reales donde apilar contenido horizontalmente y permitir un desplazamiento lateral tiene todo el sentido: galerías de imágenes, listas de productos, cards, planes de precios o incluso sitios completos con navegación horizontal.
El scroll horizontal con CSS es algo que he implementado varias veces en proyectos reales. Aunque suele parecer algo trivial, la realidad es que no basta con una sola propiedad CSS para que funcione bien, sea usable y no se rompa en distintos dispositivos ni tamaños de pantalla.
En esta guía te voy a enseñar cómo crear un scroll horizontal en CSS correctamente, cuándo usar cada técnica, qué errores evitar y cómo potenciarlo con un toque de JavaScript cuando realmente lo necesites.
Qué es el scrolling horizontal y cuándo usarlo
El scrolling horizontal es una técnica que permite al usuario desplazarse de izquierda a derecha dentro de un contenedor, en lugar del clásico scroll vertical. Parece simple, pero aplicado bien puede transformar completamente la experiencia de usuario en ciertos contextos.
Scroll horizontal vs. scroll vertical
- Scroll vertical: ideal para lectura larga y navegación tradicional.
- Scroll horizontal: perfecto para elementos visuales repetitivos, cards o contenido que se consume "en bloques".
No se trata de reemplazar el scroll vertical, sino de usarlo estratégicamente donde aporta valor.
Casos reales donde tiene sentido usarlo
Algunos escenarios donde suelo aplicarlo:
- Listas de tarjetas (cards)
- Carruseles sin dependencias de JS
- Galerías de imágenes
- Secciones mobile-first
- Planes de precios o comparativas de características
Cómo crear un scroll horizontal con CSS (método clásico)
Esta es la técnica más simple, estable y compatible. La he usado muchas veces porque funciona sin JavaScript y sin hacks raros. Aunque parezca obvio, olvidar una de las propiedades clave es uno de los errores más comunes.
Veamos cómo crear un div con scroll horizontal como el del siguiente ejemplo:

En realidad es bastante sencillo y no necesitas JavaScript ni ningún plugin mágico; solo hay unos pocos pasos que debes tener en mente. Eso sí, tampoco es tan simple como definir una sola regla CSS: hay que combinar varias propiedades correctamente. Los pasos son:
- Definir la altura (
height) del contenedor padre. - Indicar que no queremos scrolling vertical.
- Habilitar el scrolling horizontal.
Propiedades clave: overflow-x y overflow-y
Para los dos últimos pasos nos bastan un par de reglas CSS con sus valores correspondientes:
overflow-x: auto;
overflow-y: hidden;overflow-x: autohabilita el scroll horizontal solo cuando el contenido desborda el contenedor.overflow-y: hiddenevita que aparezca una barra de scroll vertical no deseada.
El valor auto es preferible a scroll porque solo muestra la barra de desplazamiento cuando realmente hace falta; con scroll la barra aparece siempre, aunque el contenido quepa. Si configuras bien el CSS, el overflow-y: hidden puede llegar a ser opcional, aunque yo lo suelo poner por precaución.
El contenedor padre: tamaño, altura y white-space
El siguiente CSS corresponde al contenedor padre, que es el encargado de realizar el desplazamiento horizontal. Aquí definimos su tamaño y el ancho de una sola vez:
Propiedades del contenedor padre
width: auto;
height: 50px;
padding: 10px;
white-space: nowrap;Básicamente establecemos el tamaño del contenedor y el espaciado interno. La propiedad white-space especifica cómo se maneja el espacio en blanco dentro del contenedor; con el valor nowrap indicamos que no debe haber saltos de línea, es decir, todo el contenido se muestra en una sola fila. Esta es, en mi experiencia, la propiedad más importante del scroll horizontal clásico.
Además, definimos una altura fija de 50px para el contenedor, mientras que el ancho lo dejamos en auto para que pueda crecer tanto como lo requiera el contenido.
Aquí está el resumen de las claves:
white-space: nowrapevita los saltos de línea y fuerza el contenido a una sola fila.- El ancho se adapta al contenido gracias a
width: auto. - La altura fija evita desbordes extraños en el eje vertical.
Los elementos hijos y por qué display: inline-block es importante
Ahora definimos el CSS para los hijos del contenedor. El concepto es sencillo: estamos creando pequeñas cajas que deben permanecer en una misma línea:
.horizontal-scroll-contenedor div {
width: 100px;
height: 50px;
margin-right: 10px;
display: inline-block;
}Puntos importantes:
display: inline-blockmantiene todos los elementos alineados en una sola fila horizontal, en lugar de apilarse verticalmente como haríadisplay: block.- El tamaño de los hijos no debe superar la altura del padre; si lo hace, el contenido se cortará.
- El
margin-rightcrea la separación visual entre cada elemento.
Ejemplo práctico de scroll horizontal con divs en HTML y CSS
Lo más importante es que los hijos tengan el mismo tamaño o menor al del padre, y que usen display: inline-block para permanecer en una misma línea. El resto del código es contextual y puedes consultarlo en los enlaces de descarga. Así quedaría el HTML:
<div class="horizontal-scroll-contenedor">
<div>Contenedor 1</div>
<div>Contenedor 2</div>
<div>Contenedor 3</div>
<div>Contenedor 4</div>
<div>Contenedor 5</div>
<div>Contenedor 6</div>
<div>Contenedor 7</div>
<div>Contenedor 8</div>
<div>Contenedor 9</div>
<div>Contenedor 10</div>
<div>Contenedor 11</div>
<div>Contenedor 12</div>
<div>Contenedor 13</div>
<div>Contenedor 14</div>
<div>Contenedor 15</div>
<div>Contenedor 16</div>
<div>Contenedor 17</div>
<div>Contenedor 18</div>
<div>Contenedor 19</div>
<div>Contenedor 20</div>
</div>CSS completo en base a lo explicado:
.horizontal-scroll-contenedor {
width: auto;
height: 50px;
padding: 10px;
overflow-x: auto;
overflow-y: hidden;
white-space: nowrap;
}
.horizontal-scroll-contenedor div {
width: 100px;
height: 50px;
margin-right: 10px;
display: inline-block;
}Y puedes ver el resultado a continuación:
Este patrón es sencillo, predecible y fácil de mantener, por eso sigo usándolo cuando no necesito efectos avanzados.
Scroll horizontal con Flexbox (la opción moderna)
Hoy en día, si tengo que elegir, Flexbox suele ser mi primera opción. Es más limpio, más semántico y elimina la necesidad de usar white-space e inline-block, que son propiedades que conceptualmente no están pensadas para maquetar layouts.
Por qué Flexbox simplifica el scroll horizontal
Con Flexbox el código queda mucho más legible. El contenedor solo necesita tres propiedades:
.flex-container {
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
}Y para los elementos hijos:
.flex-item {
flex: 0 0 auto;
}flex-wrap: nowrapevita que los elementos salten de línea, de forma equivalente awhite-space: nowrapen el método clásico.flex: 0 0 automantiene el tamaño natural de cada elemento sin que Flexbox lo estire ni lo encoja. Los tres valores son:flex-grow: 0(no crecer),flex-shrink: 0(no encoger) yflex-basis: auto(respetar el tamaño declarado).
Cuándo elegir Flexbox frente a inline-block
- Uso Flexbox cuando:
- El layout es moderno y ya usa Flexbox en otros lugares.
- Necesito alineación vertical de los elementos.
- Quiero un código más limpio y legible.
- Uso
inline-blockcuando:- Busco máxima compatibilidad con navegadores antiguos.
- Es un proyecto pequeño o muy simple.
- No quiero introducir Flexbox si el resto del código no lo usa.
Scroll snapping: el efecto imán al desplazarse
Aquí entramos en un nivel más avanzado. El scroll snapping es una técnica CSS que hace que, al terminar de desplazarse, el scroll se "enganche" automáticamente al elemento más cercano, como si tuviese un imán. El resultado se siente pulido y profesional, especialmente en móvil.
scroll-snap-type y scroll-snap-align
Estas dos propiedades crean el famoso efecto "imán":
.slider {
display: flex;
overflow-x: scroll;
scroll-snap-type: x proximity;
}
.card {
scroll-snap-align: center;
}scroll-snap-type: x proximityactiva el snap en el eje horizontal con cierta tolerancia; puedes cambiarproximitypormandatorysi quieres que el snap sea siempre obligatorio.scroll-snap-align: centeralinea cada elemento al centro del contenedor al hacer snap. Otros valores posibles sonstartyend.
Esto es ideal para:
- Experiencias mobile-first
- Carruseles táctiles
- Secciones tipo "planes" o "features"
Lo he usado bastante en proyectos responsive porque mejora muchísimo la experiencia en móvil sin necesidad de JavaScript.
Errores comunes al implementar el scroll horizontal
- El scroll no aparece
- Falta
overflow-x: autoooverflow-x: scroll. - El contenido no desborda realmente el ancho del contenedor.
- El ancho del contenedor tiene un valor fijo que impide el desbordamiento.
- Falta
- Los elementos se rompen en varias líneas
- Falta
white-space: nowrap(método clásico). - Falta
flex-wrap: nowrap(método Flexbox).
- Falta
- Problemas de altura y overflow
- Altura del contenedor mal definida o no definida.
- Elementos hijos más altos que el padre, lo que genera un scroll vertical no deseado.
- Estos errores son más comunes de lo que parece; me los he encontrado más de una vez en proyectos de distinto tamaño.
¿Hace falta JavaScript para un scroll horizontal?
En la mayoría de los casos: no. CSS puro es:
- Más rápido (sin overhead de JavaScript).
- Más simple de mantener.
- Más accesible para lectores de pantalla y tecnologías de asistencia.
- Más mantenible a largo plazo.
JavaScript solo tiene sentido cuando necesitas funcionalidades adicionales: botones de navegación con flechas, autoplay, scroll programático o animaciones más complejas.
Preguntas frecuentes sobre scroll horizontal con CSS
- ¿Se puede hacer scroll horizontal solo con CSS?
- Sí, y en la mayoría de los casos es la mejor opción. No necesitas ninguna librería externa.
- ¿Flexbox o
inline-block?- Flexbox es más moderno y limpio;
inline-blocksigue siendo válido para casos simples.
- Flexbox es más moderno y limpio;
- ¿Funciona en móvil?
- Sí, especialmente bien con gestos táctiles. Si le añades
scroll-snap, la experiencia mejora todavía más.
- Sí, especialmente bien con gestos táctiles. Si le añades
- ¿Afecta al SEO?
- No, siempre que el contenido sea accesible y visible para los crawlers. Google indexa sin problemas el contenido dentro de un
divcon scroll horizontal.
- No, siempre que el contenido sea accesible y visible para los crawlers. Google indexa sin problemas el contenido dentro de un
- ¿Cómo oculto la barra de scroll horizontal con CSS?
- Puedes ocultarla visualmente usando la pseudoclase
::-webkit-scrollbarcondisplay: none, aunque esto no es estándar en todos los navegadores:
- Puedes ocultarla visualmente usando la pseudoclase
.horizontal-scroll-contenedor::-webkit-scrollbar {
display: none;
}
/* Para Firefox */
.horizontal-scroll-contenedor {
scrollbar-width: none;
}Extra: desplazamiento automático con JavaScript usando scrollLeft
Aunque con CSS puro tenemos más que suficiente para la mayoría de los casos, JavaScript nos abre la puerta a funcionalidades más dinámicas: botones de navegación, autoplay o animaciones controladas por código. Vamos a ver cómo hacerlo con la propiedad scrollLeft y el método scrollTo().
La propiedad scrollLeft nos permite leer o establecer la cantidad de píxeles que el contenedor está desplazado horizontalmente. Para mover el scroll 200 píxeles de golpe:
// Seleccionamos el contenedor
const contenedor = document.querySelector(".horizontal-scroll-contenedor");
// Asignamos el valor de desplazamiento
contenedor.scrollLeft = 200;En JavaScript moderno puedes usar el método scrollTo() con un objeto de opciones para que el movimiento sea un deslizamiento fluido en lugar de un salto brusco:
const contenedor = document.querySelector(".horizontal-scroll-contenedor");
contenedor.scrollTo({
left: 200,
behavior: 'smooth' // Esto hace que el scroll se vea animado
});Si quieres implementar botones de navegación con flechas (siguiente/anterior), la lógica básica es sumar o restar un valor al scrollLeft actual del contenedor:
const contenedor = document.querySelector(".horizontal-scroll-contenedor");
const btnSiguiente = document.querySelector("#btn-siguiente");
const btnAnterior = document.querySelector("#btn-anterior");
btnSiguiente.addEventListener("click", () => {
contenedor.scrollBy({ left: 200, behavior: "smooth" });
});
btnAnterior.addEventListener("click", () => {
contenedor.scrollBy({ left: -200, behavior: "smooth" });
});El método scrollBy() desplaza relativamente al punto actual, lo que lo hace ideal para botones de tipo "siguiente" y "anterior" sin necesidad de calcular posiciones absolutas.
Conclusión
El scrolling horizontal con CSS no solo es posible, sino recomendable cuando se hace bien. No necesitas librerías mágicas ni JavaScript pesado; solo entender cómo funcionan overflow, display y el modelo de layout del navegador.
Después de probar varias soluciones en proyectos reales, mi recomendación es clara:
- Empieza simple con
overflow-x: autoywhite-space: nowrap. - Usa Flexbox si puedes; el código queda mucho más limpio.
- Añade
scroll-snapsolo cuando aporte valor real a la experiencia de usuario. - Evita hacks innecesarios y recurre a JavaScript solo para funcionalidades que CSS no puede cubrir.