Si llevas un tiempo con CSS, en algún momento te has plantado delante de un layout y te has preguntado: ¿esto lo hago con Flexbox o con Grid? Es una de las preguntas más frecuentes entre desarrolladores que están aprendiendo CSS moderno, y también una de las más mal respondidas en internet. La respuesta típica es «depende del caso», lo cual es verdad pero no te ayuda a tomar la decisión.
En este artículo vamos a ir más allá. Vamos a ver cómo funciona cada uno, cuáles son sus diferencias reales, y sobre todo cuándo usar cada uno — con ejemplos de código concretos, no con teoría abstracta.
En este artículo:
- Flexbox: qué es y cómo piensa
- Las propiedades de Flexbox que más vas a usar
- CSS Grid: qué es y cómo piensa
- Las propiedades de Grid que más vas a usar
- Diferencias clave entre los dos
- Cuándo usar Flexbox
- Cuándo usar CSS Grid
- Cómo combinarlos en proyectos reales
- Errores comunes
Flexbox: qué es y cómo piensa
Flexbox — nombre completo Flexible Box Layout — es un modelo de layout unidimensional. Eso quiere decir que trabaja en una sola dirección a la vez: o en fila (horizontal) o en columna (vertical). Puedes cambiar de dirección, pero en cada momento solo controlas un eje.
La idea central de Flexbox es que los elementos se distribuyen y alinean a lo largo de ese eje de forma flexible. Los elementos pueden crecer para ocupar el espacio disponible, encogerse si hay poco espacio, o mantenerse en su tamaño natural. Tú defines las reglas, y los elementos se adaptan.
Para activar Flexbox, solo necesitas display: flex en el contenedor. Todos los hijos directos se convierten automáticamente en flex items:
.contenedor {
display: flex; /* activa Flexbox */
/* por defecto: flex-direction: row (fila) */
}
/* Los hijos directos son flex items automáticamente */
.item { /* no necesitas nada especial aquí */ }
Las propiedades de Flexbox que más vas a usar
flex-direction — define el eje principal. row (por defecto) pone los elementos en fila. column los pone en columna. Con row-reverse y column-reverse inviertes el orden:
.navbar {
display: flex;
flex-direction: row; /* horizontal — el valor por defecto */
}
.sidebar {
display: flex;
flex-direction: column; /* vertical */
}
justify-content — alinea los elementos en el eje principal (el que definiste con flex-direction). Es la propiedad que más vas a usar para distribuir espacio:
.contenedor {
display: flex;
justify-content: flex-start; /* al inicio (por defecto) */
justify-content: flex-end; /* al final */
justify-content: center; /* centrado */
justify-content: space-between; /* espacio entre elementos */
justify-content: space-around; /* espacio alrededor de cada elemento */
justify-content: space-evenly; /* espacio igual entre todos */
}
align-items — alinea los elementos en el eje perpendicular (cross axis). Si tu eje principal es horizontal (fila), align-items controla la alineación vertical:
.contenedor {
display: flex;
align-items: stretch; /* estira para llenar el contenedor (por defecto) */
align-items: flex-start; /* al inicio del cross axis */
align-items: flex-end; /* al final del cross axis */
align-items: center; /* centrado en el cross axis */
align-items: baseline; /* alineados por la línea base del texto */
}
flex-wrap — por defecto, Flexbox pone todos los elementos en una sola línea aunque no quepan. Con flex-wrap: wrap, los elementos que no caben saltan a la siguiente línea:
.galeria {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.galeria-item {
width: 200px; /* si no caben en una fila, saltan a la siguiente */
height: 150px;
}
flex — propiedad shorthand para controlar cómo crece, encoge y cuál es el tamaño base de un flex item. Es la abreviatura de flex-grow, flex-shrink y flex-basis:
/* Layout clásico con sidebar */
.layout {
display: flex;
}
.sidebar {
flex: 0 0 260px; /* no crece, no encoge, ancho fijo 260px */
}
.contenido {
flex: 1; /* equivale a flex: 1 1 0 — ocupa todo el espacio restante */
}
/* Tarjetas que se distribuyen igual */
.tarjeta {
flex: 1 1 300px; /* crece, encoge, tamaño base 300px */
min-width: 0; /* importante para evitar overflow con flex: 1 */
}
Un ejemplo completo de navbar con Flexbox — el caso de uso más clásico:
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 2rem;
height: 64px;
background: #0f172a;
}
.navbar-logo {
font-size: 1.25rem;
font-weight: 700;
color: white;
}
.navbar-links {
display: flex; /* Flexbox dentro de Flexbox */
gap: 2rem;
list-style: none;
margin: 0;
padding: 0;
}
.navbar-actions {
display: flex;
gap: 1rem;
align-items: center;
}
CSS Grid: qué es y cómo piensa
CSS Grid es un sistema de layout bidimensional. Mientras Flexbox piensa en una línea, Grid piensa en una cuadrícula — filas y columnas al mismo tiempo. Defines la estructura de la página y luego colocas los elementos en las celdas que quieras.
Esto cambia la forma de pensar el layout. Con Flexbox, el tamaño de los elementos depende de su contenido y del espacio disponible. Con Grid, tú defines la estructura primero — cuántas columnas, qué anchuras — y luego los elementos se ubican en ella.
.layout {
display: grid;
grid-template-columns: 260px 1fr 200px; /* 3 columnas: fija, flexible, fija */
grid-template-rows: 64px 1fr 80px; /* 3 filas: header, main, footer */
gap: 0;
min-height: 100vh;
}
Las propiedades de Grid que más vas a usar
grid-template-columns y grid-template-rows — definen la estructura de la cuadrícula. Puedes usar píxeles, porcentajes, la unidad fr (fracción del espacio disponible) y la función repeat():
/* Tres columnas iguales */
grid-template-columns: 1fr 1fr 1fr;
grid-template-columns: repeat(3, 1fr); /* equivalente */
/* Sidebar + contenido */
grid-template-columns: 260px 1fr;
/* Columnas que se ajustan automáticamente — muy útil para galerías */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
/* Filas */
grid-template-rows: auto 1fr auto; /* header flexible, main que ocupa lo que queda, footer flexible */
grid-template-areas — te permite nombrar zonas de la cuadrícula y asignarlas visualmente. Es la propiedad más legible de Grid cuando defines layouts de página completa:
.page {
display: grid;
grid-template-columns: 260px 1fr 200px;
grid-template-rows: 64px 1fr 80px;
grid-template-areas:
"header header header"
"sidebar content aside"
"footer footer footer";
min-height: 100vh;
}
/* Asignar cada elemento a su área */
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }
grid-column y grid-row — ubican un elemento en la cuadrícula usando números de línea. Las líneas de Grid se numeran desde 1. span N indica cuántas celdas ocupa el elemento:
.elemento {
/* Ocupa desde la columna 1 hasta la 3 (columnas 1 y 2) */
grid-column: 1 / 3;
/* Ocupa 2 columnas desde donde está */
grid-column: span 2;
/* Desde la fila 2 hasta el final */
grid-row: 2 / -1; /* -1 = última línea */
}
/* Ejemplo: artículo destacado que ocupa más espacio */
.articulo-destacado {
grid-column: 1 / 3; /* dos columnas de ancho */
grid-row: 1 / 3; /* dos filas de alto */
}
gap — el espacio entre celdas. Puedes usar gap para filas y columnas a la vez, o row-gap y column-gap por separado:
.grid {
display: grid;
gap: 24px; /* 24px entre filas y columnas */
gap: 16px 24px; /* 16px entre filas, 24px entre columnas */
row-gap: 16px;
column-gap: 24px;
}
Un ejemplo completo de galería responsive con Grid:
/* Galería que se adapta automáticamente al ancho disponible */
.galeria {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 24px;
padding: 2rem;
}
.galeria-item {
border-radius: 8px;
overflow: hidden;
background: white;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
/* Elemento destacado que ocupa 2 columnas si hay espacio */
.galeria-item--destacado {
grid-column: span 2;
}
@media (max-width: 640px) {
.galeria-item--destacado {
grid-column: span 1; /* en móvil, ocupa solo 1 columna */
}
}
La diferencia real entre los dos
Ya hemos visto cómo funciona cada uno. Ahora la pregunta importante: ¿en qué se diferencian realmente?
Flexbox es unidimensional, Grid es bidimensional. Esta es la diferencia fundamental. Flexbox trabaja en un eje a la vez — o fila o columna. Grid trabaja en los dos ejes simultáneamente. Si necesitas controlar la alineación en ambas dimensiones al mismo tiempo, Grid es la herramienta.
El contenido dicta la estructura en Flexbox. La estructura dicta el contenido en Grid. Con Flexbox, los elementos se distribuyen según su contenido y el espacio disponible. Con Grid, defines la estructura primero y los elementos se ajustan a ella. Si tienes una cuadrícula de tarjetas y quieres que todas tengan exactamente el mismo tamaño independientemente del contenido, Grid lo hace de forma natural. Con Flexbox necesitarías forzarlo.
Grid alinea en dos ejes simultáneamente, Flexbox no. Con Grid puedes centrar perfectamente un elemento tanto vertical como horizontalmente con dos líneas:
/* Centrar algo perfectamente con Grid */
.contenedor {
display: grid;
place-items: center; /* shorthand de align-items + justify-items */
height: 100vh;
}
/* Con Flexbox también puedes, pero Grid es más directo para esto */
.contenedor {
display: flex;
align-items: center;
justify-content: center;
height: 100vh;
}
Flexbox es más flexible con el orden implícito, Grid es más preciso. Con Flexbox, los elementos se colocan uno detrás del otro automáticamente. Con Grid, puedes colocar un elemento exactamente donde quieras en la cuadrícula, independientemente del orden en el HTML. Eso es útil, pero también puede hacer que el código sea menos predecible si no tienes cuidado.
Cuándo usar Flexbox
Flexbox es la mejor opción cuando trabajas con componentes — elementos de interfaz que viven dentro de una sección de la página. Navbars, botones con icono y texto, formularios, tarjetas, listas de tags, grupos de elementos que necesitas alinear en una dirección.
/* Botón con icono — alineación perfecta con Flexbox */
.btn {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 20px;
border-radius: 6px;
}
/* Lista de tags — se adaptan al contenido */
.tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.tag {
padding: 4px 12px;
border-radius: 999px;
font-size: 0.875rem;
background: #f1f5f9;
}
/* Tarjeta de producto — layout interno con Flexbox */
.tarjeta {
display: flex;
flex-direction: column;
height: 100%; /* para que todas tengan la misma altura en un grid */
}
.tarjeta-contenido {
flex: 1; /* empuja el footer de la tarjeta hacia abajo */
padding: 1.5rem;
}
.tarjeta-footer {
padding: 1rem 1.5rem;
border-top: 1px solid #e2e8f0;
display: flex;
justify-content: space-between;
align-items: center;
}
/* Input con botón a la derecha */
.campo-busqueda {
display: flex;
border: 1px solid #cbd5e1;
border-radius: 6px;
overflow: hidden;
}
.campo-busqueda input {
flex: 1;
border: none;
padding: 10px 14px;
outline: none;
}
.campo-busqueda button {
padding: 10px 16px;
background: #3b82f6;
color: white;
border: none;
cursor: pointer;
}
En resumen, usa Flexbox cuando:
- Los elementos deben alinearse en una dirección (fila o columna).
- El tamaño de los elementos depende de su contenido.
- Estás construyendo un componente de interfaz, no el layout general de la página.
- Necesitas distribuir espacio sobrante entre elementos de forma flexible.
Cuándo usar CSS Grid
Grid es la opción natural cuando estás definiendo la estructura de una página o una sección compleja. Cualquier cosa que implique filas y columnas al mismo tiempo, que necesite que los elementos se alineen en dos dimensiones, o que requiera un control preciso sobre la posición de cada elemento.
/* Layout de página completa */
.app {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 64px 1fr;
grid-template-areas:
"header header"
"sidebar main";
min-height: 100vh;
}
.header { grid-area: header; background: #0f172a; }
.sidebar { grid-area: sidebar; background: #1e293b; }
.main { grid-area: main; padding: 2rem; }
/* En móvil, el sidebar se oculta o va arriba */
@media (max-width: 768px) {
.app {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main";
}
.sidebar { display: none; }
}
/* Sección de features — cuadrícula perfecta */
.features {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
padding: 4rem 2rem;
}
/* En tablet, 2 columnas */
@media (max-width: 1024px) {
.features { grid-template-columns: repeat(2, 1fr); }
}
/* En móvil, 1 columna */
@media (max-width: 640px) {
.features { grid-template-columns: 1fr; }
}
/* Dashboard con widgets de distintos tamaños */
.dashboard {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 200px;
gap: 1.5rem;
}
.widget-grande { grid-column: span 2; grid-row: span 2; }
.widget-ancho { grid-column: span 2; }
.widget-alto { grid-row: span 2; }
.widget-normal { /* ocupa 1x1 por defecto */ }
Usa Grid cuando:
- Defines el layout principal de una página o sección compleja.
- Necesitas controlar filas y columnas al mismo tiempo.
- Quieres que los elementos tengan el mismo tamaño independientemente de su contenido.
- Construyes una galería, un dashboard o cualquier diseño tipo «magazine».
- Necesitas colocar elementos en posiciones específicas de una cuadrícula.
Cómo combinarlos en proyectos reales
En la práctica, no eliges uno u otro para todo el proyecto. Los combinas constantemente. El patrón más habitual es Grid para el layout general y Flexbox para los componentes internos de cada sección.
/* NIVEL 1: Grid define el layout de la página */
.page {
display: grid;
grid-template-columns: 260px 1fr;
grid-template-rows: 64px 1fr 80px;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
min-height: 100vh;
}
/* NIVEL 2: Flexbox en la navbar (componente interno del header) */
.navbar {
grid-area: header;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 2rem;
}
/* NIVEL 2: Grid para la lista de artículos (sección con cuadrícula) */
.lista-articulos {
grid-area: content;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1.5rem;
padding: 2rem;
align-content: start; /* los artículos no se estiran para llenar el alto */
}
/* NIVEL 3: Flexbox dentro de cada tarjeta de artículo */
.articulo-card {
display: flex;
flex-direction: column;
border-radius: 8px;
border: 1px solid #e2e8f0;
overflow: hidden;
}
.articulo-card-body {
flex: 1; /* empuja el footer de la tarjeta hacia abajo */
padding: 1.5rem;
}
.articulo-card-footer {
padding: 1rem 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid #e2e8f0;
font-size: 0.875rem;
color: #64748b;
}
Este es el patrón que verás en prácticamente cualquier proyecto profesional: Grid en el nivel de página, Flexbox en el nivel de componente. No como una regla absoluta, sino como punto de partida. A veces un componente complejo necesita Grid internamente; a veces una sección sencilla basta con Flexbox.
Errores comunes con Flexbox y Grid
Usar Flexbox para todo. Es el error más habitual. Flexbox es fácil de aprender y funciona bien para muchas cosas, así que la tentación es usarlo para el layout de página también. El resultado es HTML más anidado de lo necesario y código más difícil de mantener. Cuando el diseño tiene filas Y columnas, pasa a Grid.
Olvidar min-width: 0 en flex items. Los flex items tienen min-width: auto por defecto. Eso significa que no encogen más allá del tamaño de su contenido. Si tienes un elemento con flex: 1 dentro de un flex container y el contenido del elemento es más ancho que el espacio disponible, el elemento desbordará. La solución es añadir min-width: 0:
/* Un texto largo puede hacer overflow en un flex item */
.flex-item {
flex: 1;
min-width: 0; /* permite que el elemento encoja por debajo del tamaño de su contenido */
}
.flex-item p {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
Usar porcentajes en grid-gap (obsoleto). La propiedad correcta es gap, no grid-gap. grid-gap sigue funcionando como alias, pero gap funciona tanto en Grid como en Flexbox y es el estándar actual.
No usar auto-fill vs auto-fit correctamente. Ambos crean columnas automáticamente, pero hay una diferencia importante cuando hay pocos elementos. Con auto-fill, si sobra espacio, se crean columnas vacías. Con auto-fit, las columnas vacías colapsan a cero y los elementos existentes se expanden para ocupar el espacio:
/* auto-fill: columnas vacías mantienen su espacio */
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
/* Si hay 3 elementos en un ancho de 900px → 3 ocupados + columnas vacías */
/* auto-fit: columnas vacías colapsan, los elementos llenan el espacio */
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
/* Si hay 3 elementos en un ancho de 900px → los 3 se reparten todo el espacio */
/* En general: auto-fit para listas de contenido real, auto-fill cuando quieres
que el layout no cambie aunque haya pocos elementos */
Añadir más HTML del necesario para lograr el layout. Si te encuentras añadiendo div extra solo para conseguir una distribución visual, probablemente hay una forma mejor con Grid o Flexbox. Grid en especial puede eliminar muchos niveles de anidado innecesario porque ubica elementos en dos dimensiones sin necesidad de contenedores intermedios.
Soporte en navegadores en 2026
Tanto Flexbox como CSS Grid tienen soporte completo en todos los navegadores modernos. Puedes usarlos sin prefijos y sin preocuparte por la compatibilidad en proyectos nuevos. CSS Grid tiene soporte en más del 97% de los navegadores actualmente en uso según Can I Use.
Lo único que puede tener soporte más limitado son algunas características más recientes de Grid como subgrid — que permite que los grids anidados hereden las líneas del grid padre — aunque en 2026 ya tiene buen soporte en los navegadores principales. Si necesitas soporte para navegadores muy antiguos como IE11, tanto Flexbox como Grid tienen limitaciones importantes, pero en proyectos nuevos IE11 ya no es una preocupación real.
La regla práctica para decidir
Si tuviera que resumirlo en una sola regla: empieza por Grid para el layout, usa Flexbox para los componentes. Y cuando no estés seguro, pregúntate: ¿el tamaño de los elementos depende de su contenido, o quiero que la estructura sea independiente del contenido? En el primer caso, Flexbox. En el segundo, Grid.
Con el tiempo te sale solo. Abres el inspector del navegador, ves un layout, y en segundos ya sabes qué se ha usado para construirlo. Hasta ese punto, la práctica es lo único que funciona.