La matemática detrás de CSS
flex: 1;
En Flexbox es super común utilizar este valor para hacer que un elemento cubra todo el espacio disponible de un contenedor flexible y hoy quiero contarte que significa y ponernos a prueba en casos menos usuales.
Flex es la sintaxis corta de 3 propiedades del flex layout box model flex-grow, flex-shrink y flex-basis.
Es la capacidad de "agrandamiento" o expansión de un flex item.
Es la capacidad de "achicamiento" o reducción de un flex item.
Es la base Flexible sobre la cual hacer cálculos tanto para expansión o reducción.
los valores flexibles por defecto de un flex item son:
flex-grow: 0; flex-shrink: 1; flex-basis: auto;
Te voy a explicar en profundidad esos 3 conceptos y como es que flex 1
funciona.
/* supón que viewport width son 1000px */ .flexContainer { display: flex; height: 100px; } .flexItem-1 { flex-grow: 0; flex-shrink: 0; flex-basis: 100px; background: #ef0070; }
En resumen obtienes un flex item con 100px de ancho (pero sin asignar un ancho explicito). Esto es justamente la base flexible, el ancho mínimo con el cual trabajar que teniendo en cuenta tanto "grow" como "shrink" están en 0.
Combinarla con los otro parámetros pueden empezar a hacer esto algo más confuso
.flexItem-1 { flex-grow: 1; flex-shrink: 0; flex-basis: 100px; background: #ef0070; }
Ahora actualizamos el valor de flex-grow a 1, donde 1 significa el 100% de su contenedor flexible y este es el resultado:
Como puedes imaginar el flex item a tomado el 100% del tamaño físico (1000px) de su contenedor, pero la explicación real consiste en que flex-grow: 1; se traduce así:
.flexItem-1 ahora es capaz de extenderse hasta un máximo del 100% de su contenedor flexible.
Es una posibilidad que se hizo realidad en exactamente esta condición porque el contenedor flexible no contenía ningún otro flex item. Entonces ahora agreguemos otros 2 elementos con configuraciones particulares.
.flexItem-2 { flex-grow: 1; flex-shrink: 0; flex-basis: 100px; background: #00f8fb; } .flexItem-3 { flex-grow: 1; flex-shrink: 0; flex-basis: 100px; background: #fbf57e; }
Ahora tenemos 3 elementos que se han divido el 100% del área total del contenedor flexible equitativamente. Esto ocurre por la "posibilidad" de tener el 100% del tamaño de su padre pero al haber más elementos en sus mismas condiciones el resultado fue que sean exactamente iguales en sus dimensiones.
Ahora, que tal si variamos más los valores de crecimiento:
.flexItem-3 { flex-grow: 2; flex-shrink: 0; flex-basis: 100px; background: #fbf57e; }
¿Cuál crees que será el resultado?
¿Esto tiene sentido para ti? ¿Crees que el área amarilla debería tener 500px? te explico por qué no pasó así.
El tamaño de la sección posible de crecimiento sale de restar al tamaño total del contenedor flexible, la sumatoria de las bases flexibles y dividirlo por la suma de todo el crecimiento flexible:
Tamaño total: 1000; Suma de bases flexibles: 300; Suma de crecimiento flexible: 4; (1000 - 300) / 4 = 175
Ahora calculemos el ancho del área amarilla que es el tamaño de la sección posible de crecimiento multiplicados su el crecimiento flexible y sumado por su base flexible:
Sección posible de crecimiento: 175; Crecimiento flexible: 2; Base Flexible: 100; 175 * 2 + 100 = 450
Eureka
Ahora... que tal si agregamos más propiedades que modificarían el tamaño de una caja.
.flexItem-3 { flex-grow: 2; flex-shrink: 0; flex-basis: 100px; background: #fbf57e; padding: 20px; border: 10px dashed red; }
Oh no!
Que no cunda el pánico, solo nuestra formula final no estaba completa:
Sección de posible crecimiento:
Tamaño total: 1000; Suma de bases flexibles: 300; Suma de crecimiento flexible: 4; Suma de relleno totales: 40; Suma de bordes totales: 20; (1000 - 300 - 40 - 20) / 4 = 160
Ancho de la sección amarilla:
Sección posible de crecimiento: 160; Crecimiento flexible: 2; Base Flexible: 100; Suma de relleno: 40; Suma de Bordes: 20; 160 * 2 + 100 + 40 + 20 = 480
Este calculo final no sería necesario si agregáramos el valor border-box a la propiedad box-sizing del elemento, la cual no es de ninguna manera mi recomendación.
Bien, gracias.
flex-shrink: 0;
se interpretaría como:
Bajo ningún motivo serás más pequeño de tu tamaño deseado.
hagamos un ligero cambio en la base flexible del primer flex item
.flexItem-1 { flex-grow: 1; flex-shrink: 0; flex-basis: 1000px; background: #ef0070; }
Esto generó varios fenómenos:
¿Cuándo entonces es útil un elemento inflexible?
Si viéramos el proyecto de Spotifu tendríamos que decidir cómo se comportarán las secciones laterales que si me preguntas a mi son inflexibles dejando al área central expandirse sobre el espacio disponible.
Eureka, oh wait. Ya estoy sintiendo el comentario que no leeré porque no hay comentarios sobre que debería usar un grid en este caso. si, pero estamos hablando de Flex y este ejemplo estaba bonito.
Traduce por alguna razón a:
flex-grow: 1; flex-shrink: 1; flex-basis: 0%; /* hmmm */
Ahora que sabes cómo se comporta cada propiedad en particular ya sabes porque flex:1
"ocupa todo el área disponible" (y a veces no).
Si sabes la razón técnica sobre por qué flex-basis pasa de auto a 0% por favor escríbeme.
Te dejo de tarea tambien entender que es lo que pasa si flex-shinrk es diferente de 0, o podemos averiguarlo juntos en el curso de Flexbox Layout y Componentes.