Der Unterschied zwischen Prozent- und Fr-Einheiten im CSS-Rasterlayout

Ich spiele mit CSS Grid Layout herum und stoße auf eine Frage, auf die ich keine Antwort finden kann.

Betrachten Sie das folgende Beispiel:

: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; } 
 
Column 1
Column 2
Column 3
Column 4
Column 5
Column 6
Column 7
Column 8
Column 9
Column 10
Column 11
Column 12

Wie Sie sehen können, gehen die Spalten wegen der prozentualen Breite, die mit calc(100% / var(--grid-columns)) , außerhalb der Bildschirmbreite.

Aber wenn ich fr Einheiten verwende, funktioniert es perfekt:

 :root { --grid-columns: 12; --column-gap: 10px; --row-gap: 10px; } .grid { display: grid; grid-template-columns: repeat(var(--grid-columns), 1fr); 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; } 
 
Column 1
Column 2
Column 3
Column 4
Column 5
Column 6
Column 7
Column 8
Column 9
Column 10
Column 11
Column 12

Die Ressourcen, die verwendet werden, um eine Antwort zu finden:

  • 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/

Wäre toll, wenn irgendjemand erklären könnte, warum die prozentualen Breiten einen solchen Unterschied machen.

fr

Die fr Einheit funktioniert nur mit dem freien Speicherplatz im Container.

Also in deinem Code:

 grid-template-columns: repeat(12, 1fr); 

… der freie Platz im Container verteilt sich gleichmäßig auf 12 Spalten.

Da die Spalten nur mit freiem Speicherplatz arbeiten , ist die grid-column-gap kein Faktor. Es wurde von der Behälterbreite subtrahiert, bevor die fr Länge bestimmt wurde ( Spezifikationsreferenz ).

So führt der Browser die Berechnung aus:

 (free space - gutters) / 12 = 1fr 

%

Wenn Sie Prozentsätze verwenden …

 grid-template-columns: repeat(12, calc(100% / 12)); 

… der Container ist in 12 Spalten mit jeweils einer Breite von 8,33333% unterteilt. Dies ist eine tatsächliche Länge, im Gegensatz zur Einheit fr , die nur mit freiem Speicherplatz arbeitet.

Sowohl die Spaltenlängen als auch die Gitterlücken sind in der Breite berücksichtigt.

So führt der Browser die Berechnung aus:

 8.33333% * 12 = 100% + 11 * 10px = 110px 

Es gibt einen klaren Überlauf.

(Hinweis: grid-*-gap Eigenschaften gelten nur zwischen den Rasterelementen – niemals zwischen den Elementen und dem Container. Aus diesem Grund beträgt die Anzahl der Rasterlücken 11 und nicht 13.)

Das funktioniert:

 grid-template-columns: repeat(12, calc(8.3333% - 9.1667px)); 

Was hier zusammenhängt:

  • 12 Spalten

  • Die Breite jeder Spalte wird bestimmt, indem die volle Breite des Behälters ( 100% ) genommen und durch 12 geteilt wird

     100% / 12 = 8.3333% (individual column width) 
  • dann subtrahiere die Spaltenlücken (es gibt 11)

      10px * 11 = 110px (total width of column gaps) 110px / 12 = 9.1667px (amount to be deducted from each column) 
 .grid { display: grid; grid-template-columns: repeat(12, calc(8.3333% - 9.1667px)); grid-column-gap: 10px; grid-row-gap: 10px; justify-content: center; } .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; } [class*=l-] { border: 1px solid red; } 
 
Column 1
Column 2
Column 3
Column 4
Column 5
Column 6
Column 7
Column 8
Column 9
Column 10
Column 11
Column 12

Gemäß diesem Teil der Spezifikation ist die fr-Einheit keine Länge, so dass sie “berechnet” wird, NACHDEM die Menge an freiem Platz in der Layout-Engine ermittelt wurde.

Die Variable, die Sie im ersten Beispiel erstellt haben, ist Teil einer Berechnung (100% der Breite und dividiert durch 12), sodass die Berechnung ausgeführt wird, BEVOR sie an die Layout-Engine übergeben wird.

Wenn ich Layout-Engine sage, verwende ich es als Metapher und möchte die Leute nicht mit dem Renderprozess verwechseln, der vom Browser ausgeführt wird. Ich versuche nur zu sagen, dass Sie in Ihrem ersten Beispiel eine Reihe von Zahlen präsentieren, die an den Browser angeschlossen werden, um den Renderprozess zu beginnen, und in Ihrem zweiten Beispiel präsentieren Sie mehr von einem Algorithmus / function, den der Browser verwenden kann sein Layout.