Flexbox space-between 在使用 calc() 时在末尾有额外的 1px 间隙

Flexbox space-between has extra 1px gap at the end when using calc()

我正在使用 flexbox justify-content: space-between; 开发网格系统,我注意到在某些屏幕尺寸(大约每隔一个像素)上,某些列的末尾会出现 1 个像素的间隙。

如果您开始使用下面的示例调整浏览器的大小,您可以看到 1 像素 space 出现和消失。

例子

* {
  margin: 0;
  padding: 0;
}

.row {
  display: flex;
  flex-wrap: wrap;
  max-width: 550px;
  width: 100%;
  margin: 0 auto;
  border: 2px solid #888;
  justify-content: space-between;
}

div[class^="col"] {
  border: 2px solid red;
}

.col-12 {
  flex-basis: calc(100% - 4px);
}

.col-11 {
  flex-basis: calc(11/12*100% - (1.167 - 11/12)*24px);
}

.col-10 {
  flex-basis: calc(5/6*100% - (1.167 - 5/6)*24px);
}

.col-9 {
  flex-basis: calc(3/4*100% - (1.167 - 3/4)*24px);
}

.col-8 {
  flex-basis: calc(2/3*100% - (1.167 - 2/3)*24px);
}

.col-7 {
  flex-basis: calc(7/12*100% - (1.167 - 7/12)*24px);
}

.col-6 {
  flex-basis: calc(1/2*100% - (1.167 - 1/2)*24px);
}

.col-5 {
  flex-basis: calc(5/12*100% - (1.167 - 5/12)*24px);
}

.col-4 {
  flex-basis: calc(1/3*100% - (1.167 - 1/3)*24px);
}

.col-3 {
  flex-basis: calc(1/4*100% - (1.167 - 1/4)*24px);
}

.col-2 {
  flex-basis: calc(1/6*100% - (1.167 - 1/6)*24px);
}

.col-1 {
  flex-basis: calc(1/12*100% - (1.167 - 1/12)*24px);
}
<div class="row">
  <div class="col-12">col-12</div>
  <div class="col-6">col-6</div>
  <div class="col-6">col-6</div>
  <div class="col-4">col-4</div>
  <div class="col-4">col-4</div>
  <div class="col-4">col-4</div>
  <div class="col-3">col-3</div>
  <div class="col-3">col-3</div>
  <div class="col-6">col-6</div>
  <div class="col-3">col-3</div>
  <div class="col-3">col-3</div>
  <div class="col-3">col-3</div>
  <div class="col-3">col-3</div>
  <div class="col-4">col-4</div>
  <div class="col-8">col-8</div>
  <div class="col-7">col-7</div>
  <div class="col-5">col-5</div>
  <div class="col-6">col-6</div>
  <div class="col-4">col-4</div>
  <div class="col-2">col-2</div>
</div>

这是一个有效的 Fiddle,因此您可以更轻松地调整它的大小。

JSFiddle

*注: 我知道我正在用 calc() 做一些疯狂的事情,但即使你只是减去 5px 而不是 (1.167 - 1/12)*24px),问题仍然存在。

这是 flexbox 的错误吗?

我需要做什么才能消除这些列末尾的空白?

你的问题是 col-3 和 col-6

之前:

.col-3 {
  flex-basis: calc(1/4*100% - (1.167 - 1/4)*24px);
}

之后:

.col-3 {
  flex-basis: calc(1/4*100% - (1.167 - 1/4)*25px);
}

试一试:

* {
  margin: 0;
  padding: 0;
}

.row {
  display: flex;
  flex-wrap: wrap;
  max-width: 700px;
  width: 100%;
  margin: 0 auto;
  border: 2px solid #888;
  justify-content: space-between;
}

div[class^="col"] {
  border: 2px solid red;
}

.col-12 {
  flex-basis: calc(100% - 4px);
}

.col-11 {
  flex-basis: calc(11/12*100% - (1.167 - 11/12)*24px);
}

.col-10 {
  flex-basis: calc(5/6*100% - (1.167 - 5/6)*24px);
}

.col-9 {
  flex-basis: calc(3/4*100% - (1.167 - 3/4)*24px);
}

.col-8 {
  flex-basis: calc(2/3*100% - (1.167 - 2/3)*24px);
}

.col-7 {
  flex-basis: calc(7/12*100% - (1.167 - 7/12)*24px);
}

.col-6 {
  flex-basis: calc(1/2*100% - (1.167 - 1/2)*25px);
}

.col-5 {
  flex-basis: calc(5/12*100% - (1.167 - 5/12)*24px);
}

.col-4 {
  flex-basis: calc(1/3*100% - (1.167 - 1/3)*24px);
}

.col-3 {
  flex-basis: calc(1/4*100% - (1.167 - 1/4)*25px);
}

.col-2 {
  flex-basis: calc(1/6*100% - (1.167 - 1/6)*24px);
}

.col-1 {
  flex-basis: calc(1/12*100% - (1.167 - 1/12)*24px);
}

问题

在找到解决方案之前,我稍微研究了一下这个问题。步骤如下:

首先我将所有内容转换为使用标准格式

calc(a/12 * 100% - (7/6 - a/12) * 24px) 其中 a = "col number"

接下来我开始用数字进行实验,看看没有单位的实际输出(当然)

  • 1:-17.6666...
  • 2:-7.3333...
  • 3: 3
  • 4: 13.3333...
  • 5: 23.6666...
  • 6: 34
  • 7: 44.3333...
  • 8: 54.6666...
  • 9:65
  • 10:75.3333...
  • 11: 85.6666...
  • 12: 96

从这个我们可以看出三件事

  • 能被3整除的数都是整数
  • 下一个数字重复结束x.3333...
  • 第二个数字以x.6666...
  • 结尾

注:1和2是特例,相反,因为它们的输出实际上是负数。我们可以假设他们的数字在现实世界中是正数并且与其他人一致

之后很容易查明等式中的实际问题: a/12 * 100%

所以舍入问题就是您的问题 - 即当您使用两个或更多以 x.3333...

结尾的数字时

修复

我们不希望这些舍入误差级联,因此我们有一些选择

  1. 加减数值得到中间数
  2. 添加一些半像素以减少错误并希望解决问题(仅向以 x.3333... 结尾的数字添加半像素)

示例:

  1. flex-basis: calc((8/12 - 1/6/100) * 100% - (7/6 - 8/12) * 24px);
  2. flex-basis: calc(8/12 * 100% - (7/6 - 8/12) * 24px);

我用第一个例子给我这个重复代码:

* {
  margin: 0;
  padding: 0;
}

.row {
  display: flex;
  flex-wrap: wrap;
  max-width: 550px;
  width: 100%;
  margin: 0 auto;
  border: 2px solid #888;
  justify-content: space-between;
}

div[class^="col"] {
  border: 2px solid red;
}

.col-12 {
    flex-basis: calc(12/12 * 100% - (7/6 - 12/12) * 24px);
}
.col-11 {
    flex-basis: calc((11/12 - 1/6/100) * 100% - (7/6 - 11/12) * 24px);
}
.col-10 {
    flex-basis: calc((10/12 + 1/6/100) * 100% - (7/6 - 10/12) * 24px);
}
.col-9 {
    flex-basis: calc(9/12 * 100% - (7/6 - 9/12) * 24px);
}
.col-8 {
    flex-basis: calc((8/12 - 1/6/100) * 100% - (7/6 - 8/12) * 24px);
}
.col-7 {
    flex-basis: calc((7/12 + 1/6/100) * 100% - (7/6 - 7/12) * 24px);
}
.col-6 {
    flex-basis: calc(6/12 * 100% - (7/6 - 6/12) * 24px);
}
.col-5 {
    flex-basis: calc((5/12 - 1/6/100) * 100% - (7/6 - 5/12) * 24px);
}
.col-4 {
    flex-basis: calc((4/12 + 1/6/100) * 100% - (7/6 - 4/12) * 24px);
}
.col-3 {
    flex-basis: calc(3/12 * 100% - (7/6 - 3/12) * 24px);
}
.col-2 {
    flex-basis: calc((2/12 - 1/6/100) * 100% - (7/6 - 2/12) * 24px);
}
.col-1 {
    flex-basis: calc((1/12 + 1/6/100) * 100% - (7/6 - 1/12) * 24px);
}
<div class="row">
  <div class="col-12">col-12</div>
  <div class="col-6">col-6</div>
  <div class="col-6">col-6</div>
  <div class="col-4">col-4</div>
  <div class="col-4">col-4</div>
  <div class="col-4">col-4</div>
  <div class="col-3">col-3</div>
  <div class="col-3">col-3</div>
  <div class="col-6">col-6</div>
  <div class="col-3">col-3</div>
  <div class="col-3">col-3</div>
  <div class="col-3">col-3</div>
  <div class="col-3">col-3</div>
  <div class="col-4">col-4</div>
  <div class="col-8">col-8</div>
  <div class="col-7">col-7</div>
  <div class="col-5">col-5</div>
  <div class="col-6">col-6</div>
  <div class="col-4">col-4</div>
  <div class="col-2">col-2</div>
</div>

应该可以在支持 non-rounded calc

的现代甚至大多数旧浏览器中工作

如果您想查看第二种解决方案,请发表评论,我会post。

注意:如果可以的话最好使用类似sass或更少的语言来执行这些计算,因为它们在四舍五入后还具有保留所有功能的功能一个地方这么辛苦。