CSS网格布局中百分比和fr单位之间的差异

时间:2017-07-13 20:54:51

标签: css css3 css-grid

我正在玩CSS网格布局,并遇到了一个我无法找到答案的问题。

考虑以下示例:



: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>
&#13;
&#13;
&#13;

正如您所看到的那样,由于使用calc(100% / var(--grid-columns))设置的百分比宽度,列会超出屏幕宽度。

但是,如果我使用fr单位,它就会完美运作:

&#13;
&#13;
: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;
}
&#13;
<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>
&#13;
&#13;
&#13;

用于查找答案的资源:

如果有人能解释为什么百分比宽度会产生这样的差异,那就太棒了。

2 个答案:

答案 0 :(得分:28)

fr

fr单位仅适用于容器中的可用空间。

所以在你的代码中:

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

...容器中的可用空间在12列中平均分配。

由于列只处理可用空间grid-column-gap不是一个因素。在确定fr长度之前从容器宽度中减去它(spec reference)。

以下是浏览器的计算方法:

(free space - gutters) / 12  = 1fr

%

当你使用百分比时......

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

...容器分为12列,每列宽度为8.33333%。这是一个实际长度,与fr单位不同,后者只处理自由空间。

列宽和网格间隙都考虑在宽度中。

以下是浏览器的计算方法:

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

有明显的溢出。

(注意:grid-*-gap属性仅适用于网格项之间 - 从不在项目和容器之间。这就是网格间隙数为11而不是13的原因。)

这有效:

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

分解为:

  • 12栏

  • 每列的宽度取决于容器的整个宽度(100%)并将其除以12

    100% / 12 = 8.3333% (individual column width)
    
  • 然后减去列间隙(有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; }
<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>

答案 1 :(得分:2)

According to this part of the spec fr单位不是长度,因此在确定布局引擎中可用空间量之后会“计算”。

您在第一个示例中创建的变量是计算的一部分(宽度的100%除以12),因此它在传递给布局引擎之前运行计算。

当我说布局引擎时,我将它用作隐喻,并且不想让人们混淆浏览器完成呈现的过程。我只是想说,在你的第一个例子中,你将呈现一系列插入浏览器以开始渲染过程的数字,在第二个例子中,你将展示更多的浏览器可用于制作的算法/函数它的布局。