El problema de siempre: una fila con tres zonas, y se quiere que la del centro ocupe el doble que las de los lados, en cualquier pantalla.
Hay dos herramientas para resolverlo, y la diferencia entre ellas se resume en dónde se escribe el reparto:
| Grid | Flexbox |
|---|---|
| El reparto es propiedad del padre. Se dibujan las columnas de una vez con grid-template-columns. |
El reparto es propiedad de cada hijo. Cada caja dice cuántas partes le tocan con flex. |
.padre {
display: grid;
grid-template-columns: 1fr 2fr 1fr;
}
<div class="padre"> <div class="caja izquierda">izquierda</div> <div class="caja centro">centro</div> <div class="caja derecha">derecha</div> </div>
.padre { display: grid; grid-template-columns: 1fr 2fr 1fr; gap: 8px; } .caja { background: #dcdcea; border: 2px solid #8686a8; padding: 1rem; text-align: center; font-family: Verdana, sans-serif; font-size: .85rem; }
Una sola línea reparte las tres columnas. La unidad fr
significa fracción del espacio disponible: hay 1+2+1 = 4 partes, así que la
del centro se lleva dos y las de los lados una cada una.
Resultado:
Las filas se reparten igual, cambiando la palabra columns por rows:
.padre {
display: grid;
grid-template-rows: 1fr 3fr 1fr;
}
<div class="padre"> <div class="caja izquierda">izquierda</div> <div class="caja centro">centro</div> <div class="caja derecha">derecha</div> </div>
.padre { display: grid; grid-template-rows: 1fr 3fr 1fr; gap: 8px; height: 18rem; /* las filas reparten una altura, así que hay que darla */ } .caja { background: #dcdcea; border: 2px solid #8686a8; padding: 1rem; text-align: center; font-family: Verdana, sans-serif; font-size: .85rem; }
Resultado (en un contenedor de 200 px de alto):
.padre { display: flex; }
.izquierda { flex: 1; }
.centro { flex: 2; }
.derecha { flex: 1; }
<div class="padre"> <div class="caja izquierda">izquierda</div> <div class="caja centro">centro</div> <div class="caja derecha">derecha</div> </div>
.padre { display: flex; gap: 8px; } .izquierda { flex: 1; } .centro { flex: 2; } .derecha { flex: 1; } .caja { background: #dcdcea; border: 2px solid #8686a8; padding: 1rem; text-align: center; font-family: Verdana, sans-serif; font-size: .85rem; }
El padre solo dice display: flex, que significa «pon a
tus hijos en fila». El reparto lo declara cada hijo por separado, con el
número de partes que le corresponden.
Resultado (idéntico al de Grid):
Para repartir en vertical en lugar de en horizontal, se le dice al padre que apile:
.padre {
display: flex;
flex-direction: column;
}
<div class="padre"> <div class="caja izquierda">izquierda</div> <div class="caja centro">centro</div> <div class="caja derecha">derecha</div> </div>
.padre { display: flex; flex-direction: column; gap: 8px; height: 18rem; } .izquierda { flex: 1; } .centro { flex: 3; } .derecha { flex: 1; } .caja { background: #dcdcea; border: 2px solid #8686a8; padding: 1rem; text-align: center; font-family: Verdana, sans-serif; font-size: .85rem; }
Los hijos siguen llevando su flex: 1 o
flex: 2: lo que cambia es la dirección del reparto, no la
manera de declararlo.
| Grid | Flexbox | |
|---|---|---|
| Dónde se escribe | una vez, en el padre | en cada hijo |
| Con qué | grid-template-columns: 1fr 2fr 1fr; |
flex: 1;
flex: 2;
flex: 1; |
| El padre sabe cuántos hijos hay | Sí: las columnas están dibujadas de antemano | No: coloca los que le lleguen |
| Si añades un hijo más | hay que añadir su columna | entra solo, sin tocar el padre |
| Cuándo conviene | la maqueta de la página, cuando repartes filas y columnas a la vez | una tira: un menú, una barra de botones, las zonas de una franja |
Una frase para no confundirlas: con Grid dibujas las columnas y las cajas caen dentro; con Flexbox le preguntas a cada caja cuántas partes quiere.
flex son
partes, no píxeles. flex: 2 no
significa 2 px ni 2 cm: significa el doble de partes que
flex: 1.flex: 1, no
flex-grow: 1. La forma corta deja además el tamaño de
partida en cero, y es lo que hace que la proporción salga exacta. Con
flex-grow a secas, cada caja parte del tamaño de su
contenido y la proporción se desvía.