
La siguiente es una publicación invitada de Manuel Matuzovic. Ilustra cómo funciona el crecimiento flexible, peculiaridades extrañas y todo. Luego entra en varios ejemplos sobre cómo se pueden implementar patrones de diseño comunes usando flex-grow
y flex-basis
.
Cuando me enteré de flex-grow
, Hice una demostración simple para averiguar qué hacía y cómo funcionaba.
Pensé que tenía todo resuelto, pero cuando lo probé en un sitio web que un colega hizo recientemente, nada funcionó como se esperaba. No importa lo que hicimos, el diseño no se veía ni funcionaba como lo hacía en mi demostración. Eso me hizo pensar y comencé a dudar de que yo supiera qué flex-grow
era todo.
Cómo el crecimiento flexible no funciona
Antes, vamos a profundizar en la funcionalidad de flex-grow
, Quiero explicarte en qué me equivoqué al principio.
Pensé que todos los elementos flexibles con flex-grow
ajustado a 1
tendría el mismo ancho. Si uno de los elementos tenía flex-grow
ajustado a 2
ese artículo sería dos veces más grande que todos los demás.
Esto suena genial. Parece que esto es exactamente lo que está sucediendo en el Pen que mencioné antes. El elemento principal tiene 900px de ancho, la sección con flex-grow: 2
tiene un ancho calculado de 600px y el elemento de lado con flex-grow: 1
tiene un ancho calculado de 300px.
Como puede ver, todo funciona perfectamente en esta demostración, pero no funcionó en absoluto en un ejemplo de la vida real, a pesar de que usamos exactamente el mismo CSS. Resulta que el problema no era el CSS, sino el contenido (o la falta de contenido). La demostración que hice funciona, porque al usar solo dos elementos vacíos, creé un caso de prueba que era demasiado simple para representar los detalles importantes de la propiedad.
Cómo flex-grow
realmente funciona
Acabo de describir como flex-grow
no funciona, pero les mostré una demostración que realmente hace lo que yo digo que no hace (más adelante en este artículo explicaré la razón de esto).
Para aclarar las cosas, déjame mostrarte otro bolígrafo. Tenemos exactamente la misma configuración que en el primer lápiz, pero esta vez la sección y los elementos laterales no están vacíos. Ahora la relación ya no es 2: 1 y el elemento con flex-grow establecido en 1 es en realidad más grande que el elemento con flex-grow establecido en 2.
Explicación
Si aplicamos display: flex;
al elemento principal y no cambie nada más, los elementos secundarios se apilarán horizontalmente, pase lo que pase. Si no hay suficiente espacio, se reducirán de tamaño. Si por otro lado hay espacio más que suficiente, no crecerán, porque Flexbox quiere que definamos cuánto deben crecer. Entonces, en lugar de decirle al navegador qué tan ancho debe ser un elemento, flex-grow determina cómo se distribuye el espacio restante entre los elementos flexibles y qué tan grande es el recurso compartido que recibe cada elemento.
O en otras palabras:
Un contenedor flexible distribuye el espacio libre a sus artículos (proporcionalmente a su factor de crecimiento flexible) para llenar los contenedores, o los encoge (proporcionalmente a su factor de encogimiento flexible) para evitar que se desborden.
https://drafts.csswg.org/css-flexbox/#flexibility
Demostración
El concepto es mucho más fácil de entender si lo visualizamos.
Primero configuramos el display
propiedad de nuestro elemento padre para flex
y al hacer eso, nuestros elementos secundarios se convierten en elementos flexibles y se colocan horizontalmente uno al lado del otro.
A continuación, decidimos cuántas partes del espacio extra recibe cada elemento. En nuestro ejemplo anterior, el primer elemento recibe 2/3 del espacio restante (flex-grow: 2
) y el segundo elemento 1/3 (flex-grow: 1
). Al saber cuántos valores de crecimiento flexible tenemos en total, sabemos por qué número dividir el espacio restante.
Finalmente tenemos el número de piezas distribuibles. Cada elemento recibe el número apropiado de piezas en función de su flex-grow
valor.
Cálculo
La teoría y las representaciones visuales son agradables, pero ensuciemos y hagamos los cálculos para el ejemplo anterior.
Para nuestro cálculo, necesitamos 4 números: el ancho principal, el ancho inicial de nuestra sección y nuestro elemento de lado y el número total de valores de crecimiento flexible que usaremos.
ancho principal: 900px
ancho de la sección: 99px
ancho de lado: 623px
valores totales de crecimiento flexible: 3
1. Primero tenemos que calcular el espacio restante
Eso es bastante sencillo. Tomamos el ancho de los padres y restamos el ancho inicial total de cada elemento secundario.
900 - 99 - 623 = 178
ancho principal – ancho de la sección inicial – ancho lateral inicial = espacio restante
2. A continuación, tenemos que determinar cuánto uno flex-grow
es
Ahora que tenemos el espacio restante, necesitamos determinar cuántas rebanadas queremos cortar. Lo importante aquí es que no dividimos el espacio restante por el número de elementos, sino por el número total de valores de crecimiento flexible. Entonces en nuestro caso eso es 3 (flex-grow: 2
+ flex-grow: 1
)
178 / 3 = 59.33
espacio restante / valores totales de crecimiento flexible = “un crecimiento flexible”
3. Finalmente, el espacio restante cortado se distribuye entre todos los elementos.
Según sus valores de crecimiento flexible, la sección recibe 2 cortes (2 * 59,33) y el aparte 1 (1 * 59,33). Estos números se agregan al ancho inicial de cada elemento.
99 + (2 * 59.33) = 217.66 (≈218px)
ancho de sección inicial + (valor de crecimiento flexible de la sección * “un crecimiento flexible”) = nuevo ancho
y
623 + (1 * 59.33) = 682.33 (≈682px)
ancho de lado inicial + (valor de crecimiento de flexión aparte * “un crecimiento de flexión”) = nuevo ancho
Fácil cursi, ¿verdad?
Muy bien, pero ¿por qué funciona la primera demostración?
Tenemos la fórmula, ahora averigüemos por qué obtuvimos los números que queríamos en el primer lápiz a pesar de que no sabíamos lo que estábamos haciendo.
ancho principal: 900px
ancho de la sección: 0px
ancho de lado: 0px
valores totales de crecimiento flexible: 3
1. Calcula el espacio restante
900 - 0 - 0 = 900
2. Determine cuánto es un crecimiento flexible
900 / 3 = 300
3. Distribuya el espacio restante cortado
0 + (2 * 300) = 600
0 + (1 * 300) = 300
Si el ancho de cada elemento es 0, el espacio restante es igual al ancho real del elemento principal y, por lo tanto, parece flex-grow
divide el ancho del elemento padre en partes proporcionales.
flex-grow
y flex-basis
Solo un resumen rápido: flex-grow
tomará el espacio restante y lo dividirá por la cantidad total de valores de crecimiento flexible. El cociente resultante se multiplica por el respectivo flex-grow
value y el resultado se agrega al ancho inicial de cada elemento secundario.
Pero, ¿qué pasa si no hay espacio restante o qué pasa si no queremos depender del ancho inicial de los elementos, sino de un valor que establezcamos? ¿No podemos seguir usando flex-grow
?
Por supuesto que podemos. Hay una propiedad llamada flex-basis
que define el tamaño inicial de un elemento. Si utiliza flex-basis
en conjunto con flex-grow
la forma en que se calculan los anchos cambia.
<‘flex-basis’>
Este componente establece el flex-basis
Longhand y especifica la base flexible: el tamaño principal inicial del elemento flexible, antes de que el espacio libre se distribuya de acuerdo con los factores de flexibilidad.
https://drafts.csswg.org/css-flexbox/#valdef-flex-flex-basis
La gran diferencia si aplicamos flex-basis
a un elemento es que ya no usamos su ancho inicial en nuestro cálculo, pero el valor de su flex-basis
propiedad.
He adaptado nuestro ejemplo anterior agregando flex-basis
a cada elemento. Aquí está el bolígrafo para ti.
ancho principal: 900px
ancho de la sección: 400px (valor de base flexible)
ancho de lado: 200px (valor de base flexible)
valores totales de crecimiento flexible: 3
1. Calcula el espacio restante
900 - 400 - 200 = 300
2. Determine cuánto es un crecimiento flexible
300 / 3 = 100
3. Distribuya el espacio restante cortado
400 + (2 * 100) = 600
200 + (1 * 100) = 300
En aras de la integridad, no tiene que usar valores de píxeles y esperar lo mejor, los porcentajes también funcionan.
Trabajando con el modelo de caja
Entonces, para cubrir todo, veamos qué sucede si agregamos relleno y margen. En realidad, nada demasiado especial. En el primer paso del cálculo, solo debes recordar restar los márgenes también.
Lo único a tener en cuenta es que en términos de box-sizing
flex-basis
se comporta como el width
propiedad. Eso significa que tanto el cálculo como los resultados cambian si el box-sizing
cambios de propiedad. Si box-sizing
estaba configurado para border-box
, solo trabajarías con el flex-basis
y margin
valores en su cálculo, porque el padding
ya está incluido en el ancho.
Algunos ejemplos útiles
Muy bien, basta de matemáticas. Déjame darte algunos ejemplos de cómo puedes establecer flex-grow
eficazmente en sus proyectos.
No más width: [ x ]%
Debido al hecho de que el espacio restante se distribuye automáticamente, ya no necesitamos pensar en los valores de ancho, si queremos que nuestros elementos secundarios llenen el elemento principal.
Vea el Pen QyWEBb de Manuel Matuzovic (@matuzo) en CodePen.
El diseño líquido de 3 columnas del “Santo Grial” con anchos de píxel
Mezclar anchos fijos y fluidos en diseños de columnas es posible con flotador, pero no es ni intuitivo ni fácil ni flexible. Por supuesto, con Flexbox y un poco de magia de crecimiento flexible y base flexible es pan comido.
Vea el Pen jbRjMG de Manuel Matuzovic (@matuzo) en CodePen.
Llenar el espacio restante con cualquier elemento
Si, por ejemplo, tiene un campo de entrada al lado de una etiqueta y desea que el campo de entrada llene el resto del espacio, ya no necesita trucos feos.
Vea el Pen eJYdWV de Manuel Matuzovic (@matuzo) en CodePen.
Puede encontrar más ejemplos en Philip Waltons Solved by Flexbox.
Escuchando las especificaciones
Según las especificaciones, deberíamos utilizar el flex
taquigrafía en lugar de flex-grow
directamente.
Se anima a los autores a controlar la flexibilidad utilizando el flex
taquigrafía en lugar de flex-grow
directamente, ya que la abreviatura restablece correctamente cualquier componente no especificado para adaptarse a usos comunes.
https://drafts.csswg.org/css-flexbox/#flex-grow-property
¡Pero ten cuidado! Si solo usa flex: 1;
algunos de los ejemplos anteriores ya no funcionarán, porque los valores establecidos para los usos comunes no son iguales a los valores predeterminados y, por lo tanto, interfieren con nuestras necesidades.
Si quieres usar flex
para nuestro caso de uso, debe definirlo así:
flex: 2 1 auto; /* (<flex-grow> | <flex-shrink> | <flex-basis>) */
Aprendizaje de Flexbox
Si desea obtener más información sobre Flexbox, consulte estos excelentes recursos:
- Una guía completa de Flexbox por Chris Coyier
- Aventuras de Flexbox por Chris Wright
- Flexbox Froggy de Thomas Park
- ¿Qué es el Flexbox? por Wes Bos
- flexboxin5
- Probador Flexbox de Mike Riethmuller
Resumen y lecciones aprendidas
Es flex-grow
¿extraño? No, en absoluto. Solo tenemos que entender cómo funciona y qué hace. Si un elemento tiene flex-grow
ajustado a 3
no significa que sea 3 veces más grande que un elemento que tiene flex-grow
establecido en 1, pero significa que obtiene 3 veces más píxeles agregados a su ancho inicial que el otro elemento.
Aprendí mi lección probando flex-grow con dos elementos vacíos, lo que me dio una comprensión completamente diferente de lo que realmente hace la propiedad y esto, por supuesto, me llevó a conclusiones erróneas. Debería comprobar las cosas nuevas en un entorno que sea lo más realista posible, para obtener la mejor impresión de cómo funciona y se comporta realmente.