La diferencia entre porcentaje y unidades fr.

Resuelto Morpheus asked hace 7 años • 3 respuestas

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>
Expandir fragmento

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 frunidades, 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.

Morpheus avatar Jul 14 '17 03:07 Morpheus
Aceptado

fr

La frunidad 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-gapno es un factor. Se restó del ancho del contenedor antes de frdeterminar 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 frunidad, 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-*-gaplas 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 12

    100% / 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

Michael Benjamin avatar Jul 13 '2017 23:07 Michael Benjamin

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 = 1frpor 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 Xfresta 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 autopará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 0pxdebes usarlo minmax(0,Xfr)como Xla 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/

Ignacio Bustos avatar Nov 29 '2021 12:11 Ignacio Bustos

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.

edswartz avatar Jul 13 '2017 21:07 edswartz