【问题标题】:Inconsistent margin between flex items on last row最后一行的弹性项目之间的边距不一致
【发布时间】:2016-09-20 15:39:06
【问题描述】:

我正在使用flex。两个 div 元素之间似乎存在意外的边距差异 - 第三行与前两行相比,div 之间的边距不同:

如何修改代码,使第三行的边距与前两行相同?

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.container:after {
  flex: 1;
  content: '';
}

.container form {
  width: 100%;
  display: flex;
}

.container .comment {
  flex: 1;
}

.square {
  padding: 10px;
  width: calc(100% / 9);
  margin: 0.7vw 0 0.7% 1vw;
  background: red;
}
<div class="container">
  <form method="post" style="margin: 0.7vw 0 0.7% 1vw;">
    <input class="comment" type="text">
    <input type="submit">
  </form>

  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
  <div class="square">
  </div>
</div>

JsFiddle:https://jsfiddle.net/4ydyoqmx/

【问题讨论】:

    标签: html css flexbox


    【解决方案1】:

    问题是你的伪元素正在消耗最后一行的所有可用空间。

    是的,这样做是为了抵消justify-content: space-between 对两个弹性项目的影响,这会导致它们出现在相反的两端......

    ...但它也消除了space-between 在项目填满行时提供的比例间距。

    在使用特定的最后一行对齐属性修改 flex 规范之前,您可以实施解决此问题的 hack:

    在最后一个真实项目之后添加不可见的弹性项目。

    在下面的示例中,我在您的代码中添加了七个虚拟项目。

    .container {
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
    }
    
    /*
    .container:after {
      flex: 1;
      content: '';
    }
    */
    
    .invisible { visibility: hidden; }
    
    .container form {
      width: 100%;
      display: flex;
    }
    
    .container .comment {
      flex: 1;
    }
    
    .square {
      padding: 10px;
      width: calc(100% / 9);
      margin: 0.7vw 0 0.7% 1vw;
      background: red;
    }
    <div class="container">
      <form method="post" style="margin: 0.7vw 0 0.7% 1vw;">
        <input class="comment" type="text">
        <input type="submit">
      </form>
    
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      <div class="square"></div>
      
      <div class="square invisible"></div>
      <div class="square invisible"></div>
      <div class="square invisible"></div>
      <div class="square invisible"></div>
      <div class="square invisible"></div>
      <div class="square invisible"></div>
      <div class="square invisible"></div>
    </div>

    Revised Fiddle

    更多信息:


    旁注

    您很有可能会在使用此规则时遇到一些问题:

    .square { margin: 0.7vw 0 0.7% 1vw; }
    

    flexbox specification 建议不要在弹性容器中使用百分比边距和填充。

    作者应完全避免在弹性项目的填充或边距中使用百分比,因为它们在不同的浏览器中会出现不同的行为。

    这里还有一些:

    4.2. Flex Item Margins and Paddings

    弹性项目的百分比边距和内边距可以通过以下任一方式解决:

    • 他们自己的轴(左/右百分比根据宽度解析,顶部/底部根据高度解析),或者,
    • 内联轴(左/右/上/下百分比都根据宽度解析)

    用户代理必须选择这两种行为之一。

    注意:这种差异很糟糕,但它准确地捕捉到了世界的当前状态(实现之间没有共识,CSSWG 内部也没有共识)。 CSSWG 的意图是让浏览器集中在其中一种行为上,届时将修改规范。

    【讨论】:

    • 感谢您的精彩回答(实际上非​​常棒!)。虽然我没有想过添加不可见的 div 以使最后一行镜像前两行,但我不相信这将是最方便的解决方案,因为我稍后计划在 foreach 循环中使用我的代码,我感觉必须使用 PHP 函数来计算 div 的数量并根据有多少,替换隐藏的 div 会有点复杂。我赞成您的回答,因为我觉得这对于遇到相同问题的其他用户来说会很棒:)
    • 嗨,迈克尔,已经一年多了,我想知道唯一的选择是否仍然是实施“黑客”,或者规范是否已经修改?
    • 嗨。 flex 没有任何改变。最后一行对齐问题仍然存在。然而,随着 CSS Grid 的出现,现在有一个干净、简单和容易的解决方案:jsfiddle.net/4ydyoqmx/12
    【解决方案2】:

    有几种不同的方法可以做到这一点,具体取决于您希望“方块”如何响应:

    flex-grow:

    .square {
        flex-grow: 1;
        padding: 10px;
        width: calc(100% / 9);
        margin: 0.7vw 0 0.7% 1vw;
        background: red;
    }
    

    小提琴:https://jsfiddle.net/4ydyoqmx/2/

    inline-block:

    .square {
        display: inline-block;
        padding: 10px;
        width: calc(100% / 9);
        margin: 0.7vw 0 0.7% 1vw;
        background: red;
    }
    

    小提琴:https://jsfiddle.net/4ydyoqmx/4/

    第三个选项:

    .container:after 中删除了content: '',因为这会导致问题

    【讨论】:

    • 我想到目前为止最好的选择是使用flex-grow。我试图避免你的第二个建议,因为我希望最后一个 div 在提交按钮结束的地方结束(如果你明白我的意思)
    • 删除content: '' 看看你喜欢什么
    • 它将一个 div 浮动到右边,这不是我想要的
    • 你的选项,我个人最喜欢flex选项。
    【解决方案3】:

    这是.container 上的justify-content: space-between 设置(与flex-wrap: wrap; 结合使用): 它会在那些被填充的行中分配元素,但在最后一行看起来不太好,因此它会在这些元素之间留下预定义/默认的边距。 (这类似于两端对齐的文本段落)

    避免这种情况的一种方法是简单地删除justify-content: space-between,从而将其设置为默认leftalignment(但它们将不再分布在整个宽度上):

    https://jsfiddle.net/h8ejaob7/

    【讨论】:

    • 我试图避免这种情况,因为我希望最后一个 div 在提交按钮结束的地方结束(如果你明白我的意思)
    • 我真的看不出这是被否决的原因(解释?)。但似乎一个很大的反对者一直在考虑所有这些答案......
    • 我赞成你的回答,因为我相信它包含有价值的信息,不值得反对:)
    【解决方案4】:

    之所以这样做,是因为您要使用中间的空格来证明内容的合理性。所以在屏幕上它不能容纳第 7 个 div,所以它只在屏幕上放置 6 个 div,并在 6 个 div 元素之间放置相等的空间。但在最后一行只有 2 个 div,这意味着你的第 3 行没有完全填充 div 元素.这就是为什么它没有像在上线的 div 上那样放置空间。

    如果你再放 4 个 div,那么你会得到与上一行一样的效果。

    【讨论】:

      【解决方案5】:

      这个问题可以通过将这段代码添加到你的 css 中来解决。

      *{margin:0px;
      padding:0px}
      

      希望它有效..

      【讨论】:

      • @SangameshDavey 它没有解决问题,see here。确保调整大小,使前两行中有六个项目。