La diferencia entre porcentaje y unidades fr.
Estoy jugando con CSS Grid Layout y encontré una pregunta para la que no puedo encontrar una respuesta.
Considere el siguiente ejemplo:
:root {
--grid-columns: 12;
--column-gap: 10px;
--row-gap: 10px;
}
.grid {
display: grid;
grid-template-columns: repeat(var(--grid-columns), calc(100% / var(--grid-columns)));
grid-column-gap: var(--column-gap);
grid-row-gap: var(--row-gap);
justify-content: center;
}
[class*=l-] {
border: 1px solid red;
}
.l-1 {
grid-column-start: span 1;
}
.l-2 {
grid-column-start: span 2;
}
.l-3 {
grid-column-start: span 3;
}
.l-4 {
grid-column-start: span 4;
}
.l-5 {
grid-column-start: span 5;
}
.l-6 {
grid-column-start: span 6;
}
.l-7 {
grid-column-start: span 7;
}
.l-8 {
grid-column-start: span 8;
}
.l-9 {
grid-column-start: span 9;
}
.l-10 {
grid-column-start: span 10;
}
.l-11 {
grid-column-start: span 11;
}
.l-12 {
grid-column-start: span 12;
}
<div class="grid">
<div class="l-6">Column 1</div>
<div class="l-6">Column 2</div>
<div class="l-3">Column 3</div>
<div class="l-4">Column 4</div>
<div class="l-3">Column 5</div>
<div class="l-2">Column 6</div>
<div class="l-1">Column 7</div>
<div class="l-10">Column 8</div>
<div class="l-1">Column 9</div>
<div class="l-5">Column 10</div>
<div class="l-5">Column 11</div>
<div class="l-2">Column 12</div>
</div>
Como puede ver, las columnas salen del ancho de la pantalla debido al ancho porcentual establecido con calc(100% / var(--grid-columns))
.
Pero si uso fr
unidades, funciona perfectamente:
Mostrar fragmento de código
Los recursos utilizados para encontrar una respuesta:
https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns
https://css-tricks.com/snippets/css/complete-guide-grid/
https://www.w3.org/TR/css-grid-1/
Sería fantástico si alguien pudiera explicar por qué los anchos porcentuales marcan tanta diferencia.
fr
La fr
unidad funciona sólo con el espacio libre en el contenedor.
Entonces en tu código:
grid-template-columns: repeat(12, 1fr);
... el espacio libre en el contenedor se distribuye equitativamente entre 12 columnas.
Dado que las columnas solo se ocupan del espacio libre , grid-column-gap
no es un factor. Se restó del ancho del contenedor antes de fr
determinar la longitud ( referencia de especificaciones ).
Así es como el navegador realiza el cálculo:
(free space - gutters) / 12 = 1fr
%
Cuando usas porcentajes...
grid-template-columns: repeat(12, calc(100% / 12));
... el contenedor está dividido en 12 columnas, cada una con un ancho de 8,33333%. Se trata de una longitud real, a diferencia de la fr
unidad, que sólo se ocupa del espacio libre.
Tanto la longitud de las columnas como los espacios de la cuadrícula se tienen en cuenta en el ancho.
Así es como el navegador realiza el cálculo:
8.33333% * 12 = 100%
+
11 * 10px = 110px
Hay un claro desbordamiento.
(Nota: grid-*-gap
las propiedades se aplican solo entre elementos de la cuadrícula, nunca entre elementos y el contenedor. Es por eso que el número de espacios en la cuadrícula es 11, no 13).
Esto funciona:
grid-template-columns: repeat(12, calc(8.3333% - 9.1667px));
Que se descompone en esto:
12 columnas
el ancho de cada columna se determina tomando el ancho total del contenedor (
100%
) y dividiéndolo por 12100% / 12 = 8.3333% (individual column width)
luego resta los espacios entre columnas (hay 11)
10px * 11 = 110px (total width of column gaps) 110px / 12 = 9.1667px (amount to be deducted from each column)
Mostrar fragmento de código
Respuesta tardía pero 100% vale la pena.
Tengo que añadirle a Michael Benjamin una cosa importante, especificada en el 3.
Resumen con todos los casos recogidos.
1. Uso con%
Las columnas de cuadrícula calculadas con %
no tienen en cuenta los márgenes (también conocidos como espacios). Por lo tanto, debe agregar los píxeles de los espacios agregados al cálculo. entoncestotalGridWidth = SUM(...%) + gutters = ~100% + gutters
2. Uso confr
El problema anterior no ocurre (excepción en el número 3), ya que incluye calcular el espacio libre también con los huecos. entonces el cálculo es el siguiente: (free space - gutters) / 12 = 1fr
por lo tanto, aquí puedes obtener proporciones como fracciones en lugar de porciones como porcentajes.
O en otras palabras:
grid-template-columns: repeat(12, 1fr);
3. Uso conminmax(0,Xfr)
De forma predeterminada, el motor de diseño del navegador utiliza para calcular Xfr
esta fórmula minmax(auto,Xfr)
que se basa en el tamaño mínimo de sus elementos, y cuando se espera que alguno de esos elementos o elementos internos crezca en tamaño indefinidamente, con cosas como width:100%
el auto
parámetro, el caso 2 aún se ejecutará. a veces con rejillas desbordadas. Para evitar esto, debemos forzar al navegador a usar un método que pueda reducir los elementos hasta su mínimo real, para lo cual 0px
debes usarlo minmax(0,Xfr)
como X
la fracción deseada.
O en otras palabras, para tu caso anterior:
grid-template-columns: repeat(12, minmax(0,1fr));
Esto será a prueba de balas para sus problemas desbordados.
Puedes leer más en este artículo que he encontrado:
https://css-tricks.com/preventing-a-grid-blowout/
Según esta parte de la especificación, la unidad fr no es una longitud, por lo que se "calcula" DESPUÉS de determinar la cantidad de espacio libre disponible dentro del motor de diseño.
La variable que creó en su primer ejemplo ES parte de un cálculo (100% del ancho y se divide por 12), por lo que ejecuta el cálculo ANTES de pasar al motor de diseño.
Cuando digo motor de diseño, lo uso como metáfora y no quiero confundir a la gente con el proceso de renderizado que realiza el navegador. Solo intento decir que en su primer ejemplo está presentando una serie de números que se conectan al navegador para comenzar el proceso de renderizado y en su segundo ejemplo está presentando más un algoritmo/función que el navegador puede usar para crear su trazado.