Cuando aplica una propiedad CSS a un elemento, suceden muchas cosas bajo el capó. Por ejemplo, digamos que tenemos algo de HTML como este:
<div class="parent">
<div class="child">Child</div>
<div class="child">Child</div>
<div class="child">Child</div>
</div>
Y luego escribimos algo de CSS …
.parent {
display: flex;
}
Técnicamente, estos no son los únicos estilos que aplicamos cuando escribimos esa línea de CSS anterior. De hecho, se aplicarán un montón de propiedades a la .child
elementos aquí, como si escribiéramos estos estilos nosotros mismos:
.child {
flex: 0 1 auto; /* Default flex value */
}
¡Eso es raro! ¿Por qué estos elementos tienen estos estilos adicionales aplicados a pesar de que no escribimos ese código? Bueno, eso se debe a que algunas propiedades tienen valores predeterminados que luego pretendemos ser anulados por nosotros. Y si no sabemos que estos estilos se están aplicando cuando escribimos CSS, nuestros diseños pueden volverse bastante confusos y difíciles de administrar.
Ese flex
La propiedad anterior es lo que se conoce como propiedad CSS abreviada. Y realmente lo que está haciendo es configurar tres propiedades CSS separadas al mismo tiempo. Entonces, lo que escribimos arriba es lo mismo que escribir esto:
.child {
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
}
Por lo tanto, una propiedad abreviada agrupa un montón de propiedades CSS diferentes para facilitar la escritura de varias propiedades a la vez, precisamente como el background
propiedad donde podemos escribir algo como esto:
body {
background: url(sweettexture.jpg) top center no-repeat fixed padding-box content-box red;
}
Intento evitar las propiedades taquigráficas porque pueden resultar bastante confusas y, a menudo, tiendo a escribir las versiones a mano larga solo porque mi cerebro no puede analizar las líneas largas de valores de propiedad. Pero se recomienda utilizar la abreviatura cuando se trata de flexbox, que es … raro … es decir, hasta que comprenda que el flex
la propiedad está haciendo mucho trabajo y cada una de sus subpropiedades interactúa con las demás.
Además, los estilos predeterminados son algo bueno porque no necesitamos saber qué hacen estas propiedades de flexbox el 90% del tiempo. Por ejemplo, cuando uso flexbox, tiendo a escribir algo como esto:
.parent {
display: flex;
justify-content: space-between;
}
Ni siquiera necesito preocuparme por los elementos secundarios o los estilos que se les han aplicado, ¡y eso es genial! En este caso, alineamos los elementos secundarios uno al lado del otro y luego los espaciamos equitativamente entre sí. Dos líneas de CSS te dan mucho poder aquí y eso es lo mejor de flexbox y estos estilos heredados: no tienes que entender toda la complejidad bajo el capó si solo quieres hacer lo mismo el 90% del tiempo . Es notablemente inteligente porque toda esa complejidad está oculta a la vista.
Pero, ¿y si queremos entender cómo flexbox, incluido el flex-grow
, flex-shrink
, y flex-basis
propiedades – realmente funcionan? ¿Y qué cosas interesantes podemos hacer con ellos?
Simplemente vaya al Almanaque de trucos de CSS. ¡Hecho!
Es una broma. Comencemos con una descripción general rápida que está un poco simplificada y regresemos al predeterminado flex
propiedades que se aplican a los elementos secundarios:
.child {
flex: 0 1 auto;
}
Estos estilos predeterminados le dicen a ese elemento hijo cómo estirarse y expandirse. Pero cada vez que veo que se usa o se anula, me resulta útil pensar en estas propiedades taquigráficas como esta:
/* This is just how I think about the rule above in my head */
.child {
flex: [flex-grow] [flex-shrink] [flex-basis];
}
/* or... */
.child {
flex: [max] [min] [ideal size];
}
Ese primer valor es flex-grow
y está configurado para 0
porque, de forma predeterminada, no queremos que nuestros elementos se expandan en absoluto (la mayoría de las veces). En cambio, queremos que cada elemento dependa del tamaño del contenido que contiene. He aquí un ejemplo:
.parent {
display: flex;
}
He agregado el contenteditable
propiedad a cada uno .child
elemento de arriba para que pueda hacer clic en él y escribir aún más contenido. ¿Ves cómo responde? Ese es el comportamiento predeterminado de un elemento de caja flexible: flex-grow
se establece en 0
porque queremos que el elemento crezca en función del contenido que contiene.
¡Pero! Si tuviéramos que cambiar el valor predeterminado del flex-grow
propiedad de 0
a 1
, como esto…
.child {
flex: 1 1 auto;
}
Entonces todos los elementos crecerán para ocupar una porción igual del elemento .parent:
Esto es exactamente lo mismo que escribir …
.child {
flex-grow: 1;
}
… E ignorando los otros valores porque de todos modos se han establecido por defecto. Creo que esto me confundió durante tanto tiempo cuando comencé a trabajar con diseños flexibles. Vería un código que agregaría solo flex-grow
y me pregunto de dónde vienen los otros estilos. Era como un misterio de asesinato exasperante que simplemente no podía descifrar.
Ahora, si quisiéramos hacer que solo uno de estos elementos creciera más que los otros, solo tendríamos que hacer lo siguiente:
.child-three {
flex: 3 1 auto;
}
/* or we could just write... */
.child-three {
flex-grow: 3;
}
¿Es este código extraño para mirar incluso una década después de que flexbox aterrizara en los navegadores? Ciertamente lo es para mí. Necesito poder cerebral adicional para decir, “Ah, máximo, mínimo, tamaño ideal”, cuando estoy leyendo la taquigrafía, pero se vuelve más fácil con el tiempo. De todos modos, en el ejemplo anterior, los dos primeros elementos secundarios ocuparán proporcionalmente la misma cantidad de espacio, pero ese tercer elemento intentará crecer hasta tres veces el espacio que los demás.
Aquí es donde las cosas se ponen raras porque todo depende del contenido de los elementos secundarios. Incluso si nos ponemos flex-grow
a 3
, como hicimos en el ejemplo anterior y luego agregamos más contenido, el diseño hará algo extraño y peculiar como esto:
¡Esa segunda columna ahora está ocupando demasiado espacio! Volveremos a esto más adelante, pero por ahora, es importante recordar que el contenido de un elemento flexible tiene un impacto en cómo flex-grow
, flex-shrink
, y flex-basis
trabajar juntos.
OK así que ahora para flex-shrink
. Recuerde que ese es el segundo valor de la taquigrafía:
.child {
flex: 0 1 auto; /* flex-shrink = 1 */
}
flex-shrink
le dice al navegador cuál debe ser el tamaño mínimo de un elemento. El valor predeterminado es 1
, que dice: “Ocupa la misma cantidad de espacio en todo momento”. ¡Sin embargo! Si tuviéramos que establecer ese valor en 0
como esto:
.child {
flex: 0 0 auto;
}
… entonces le estamos diciendo a este elemento que no se encoja en absoluto ahora. ¡Quédate del mismo tamaño, maldito elemento! es esencialmente lo que dice este CSS, y eso es precisamente lo que hará. Regresaremos a esta propiedad en un momento una vez que veamos el valor final en esta abreviatura.
flex-basis
es el último valor que se agrega de forma predeterminada en el flex
taquigrafía, y así le decimos a un elemento que se ciña a un tamaño ideal. De forma predeterminada, está configurado en auto
lo que significa “Usar mi altura o ancho”. Entonces, cuando establecemos un elemento padre en display: flex
…
.parent {
display: flex;
}
.child {
flex: 0 1 auto;
}
Obtendremos esto por defecto en el navegador:
¿Observa cómo todos los elementos tienen el ancho de su contenido por defecto? Eso es porque auto
está diciendo que el tamaño ideal de nuestro elemento está definido por su contenido. Para hacer que todos los elementos ocupen el espacio completo del padre, podemos configurar los elementos secundarios en width: 100%
, o podemos configurar el flex-basis
a 100%
, o podemos establecer flex-grow
a 1
.
¿Tiene sentido? ¡Es extraño, eh! Lo hace cuando lo piensas. Cada uno de estos valores abreviados impacta al otro y es por eso que se recomienda escribir esta abreviatura en primer lugar en lugar de establecer estos valores de forma independiente entre sí.
OK, sigo adelante. Cuando escribimos algo como esto …
.child-three {
flex: 0 1 1000px;
}
Lo que le estamos diciendo al navegador aquí es que configure el flex-basis
a 1000px
o “por favor, por favor, intente tomar 1000px
del espacio.” Si eso no es posible, entonces el elemento ocupará ese espacio proporcionalmente a los otros elementos.
Puede notar que en pantallas más pequeñas este tercer elemento no es en realidad un 1000px
! Eso es porque es realmente una sugerencia. Todavía tenemos flex-shrink
aplicado, lo que le dice al elemento que se encoja al mismo tamaño que los otros elementos.
Además, agregar más contenido a los otros niños seguirá teniendo un impacto aquí:
Ahora, si quisiéramos evitar que este elemento se encoja en absoluto, podríamos escribir algo como esto:
.child-three {
flex: 0 0 1000px;
}
Recordar, flex-shrink
es el segundo valor aquí y, al establecerlo en 0, estamos diciendo: “No te encojas nunca, idiota”. Y así no lo hará. El elemento incluso saldrá del elemento padre porque nunca será más corto que 1000px
ancho:
Ahora todo esto cambia si configuramos flex-wrap
al elemento padre:
.parent {
display: flex;
flex-wrap: wrap;
}
.child-three {
flex: 0 0 1000px;
}
Veremos algo como esto:
Esto se debe a que, de forma predeterminada, los elementos flexibles intentarán encajar en una línea, pero flex-wrap: wrap
ignorará eso por completo. Ahora, si esos elementos flexibles no caben en el mismo espacio, pasarán a una nueva línea.
De todos modos, estas son solo algunas de las formas en que flex
las propiedades chocan entre sí y por qué es tan valioso entender cómo funcionan estas propiedades bajo el capó. Cada una de estas propiedades puede afectar a la otra, y si no entiendes cómo funciona una propiedad, entonces no entiendes cómo funciona ninguna de ellas, ¡lo que ciertamente me confundió antes de comenzar a investigar esto!
Pero para resumir:
- Intenta usar el
flex
taquigrafía - Recuerde el tamaño máximo, mínimo e ideal al hacerlo
- Recuerde que el contenido de un elemento también puede afectar la forma en que estos valores funcionan juntos.