【问题标题】:Flex-box: Align last row to gridFlex-box:将最后一行与网格对齐
【发布时间】:2013-09-15 15:40:44
【问题描述】:

我有一个简单的 flex-box 布局,其中包含如下容器:

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

现在我希望最后一行中的项目与其他项目对齐。应该使用justify-content: space-between;,因为可以调整网格的宽度和高度。

目前看起来像

在这里,我希望右下角的项目位于“中间列”中。实现这一目标的最简单方法是什么?这是一个小的jsfiddle,它显示了这种行为。

.exposegrid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.exposetab {
  width: 100px;
  height: 66px;
  background-color: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(0, 0, 0, 0.4);
  border-radius: 5px;
  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
  margin-bottom: 10px;
}
<div class="exposegrid">
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
</div>

【问题讨论】:

标签: css flexbox grid-layout


【解决方案1】:

添加自动填充空间的::after。无需污染您的 HTML。这是一个显示它的代码笔:http://codepen.io/DanAndreasson/pen/ZQXLXj

.grid {
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.grid::after {
  content: "";
  flex: auto;
}

【讨论】:

  • 有没有可能让它以某种方式在空间周围工作?
  • @DanAndreasson 有两个问题,它不是从左边开始的(比如 space-between),而且最后一行的项目之间的空间与上一行不同(模拟一些固定的“任意大小”网格中的宽度项目 - 与两者有关)...codepen.io/anon/pen/gPoYZE 我想要的是保持“策略”(空间或空间之间),但从左侧开始,就像前几行一样。 . 我想知道,是否可以概括您的惊人解决方案。
  • 这仅适用于项目有填充来分隔它们,并且每组 4 个的组合百分比宽度等于 100%。In this codepen 我从 .grid 中删除了 justify-content: space-between; 并删除了 .grid:after它的工作原理相同。现在,如果您尝试了like this,它就会完全崩溃。请注意,每组 4 个的宽度加起来不等于 100%。在OP's fiddle 中,宽度以像素为单位设置,因此您的解决方案doesn't work 这种情况。
  • 尝试此解决方案时,最初,最后一行缺少的项目没有与space-between 正确分布。但是,当我将.grid:afterflex-basis 设置为与网格中其他项目相同的大小(每个断点,覆盖上述默认/基本模块代码)时,最后一行正确展开。似乎可以在 Safari、iOS、Firefox、Chrome(需要测试 IE)上运行,并且在我的初始实现中,我的最大行大小是 3。
  • 根据我的需要,这适用于以下修改:{ content: "";flex: 0 0 32%;max-width: 480px;},我通过媒体查询更改更改了最大宽度,因此网格在所有宽度上都是完美的。
【解决方案2】:

一种技术是插入一些高度为零的额外元素(与您期望的连续元素的最大数量一样多)。空间仍然被分割,但多余的行折叠成空:

http://codepen.io/dalgard/pen/Dbnus

body {
  padding: 5%;
}

div {
  overflow: hidden;
  background-color: yellow;
}

ul {
  display: flex;
  flex-wrap: wrap;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;
}

li {
  flex: 1 0 200px;
  height: 200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;
}
li:empty {
  height: 0;
  border: none;
}

*,
:before,
:after {
  box-sizing: border-box;
}
<div>
  <ul>
    <li>a</li>
    <li>b</li>
    <li>c</li>
    <li>d</li>
    <li>e</li>
    <li>f</li>
    <li>g</li>
    <li>h</li>
    <li>i</li>
    <li>j</li>
    <li>k</li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

未来,这可能会通过使用多个::after(n) 来实现。

【讨论】:

  • 不幸的是,这以非语义方式污染了标记,但它完全有效。 :S 我希望我知道任何其他不需要非语义元素的方式来复制这种行为,flexbox 或其他方式。
  • 同意,它很脏,但它可以工作,并且比很多黑客都少hacky。去死吧,我一直在使用它,直到 ::after(12) 获得支持,或者他们添加了一些额外的 justify 选项。真的很遗憾,因为 flexbox justify 目前的工作方式是完全错误的!如果您要证明一段文本的合理性,那么您永远不会尝试证明最后一行的合理性。绝对应该是一个选择,我不敢相信他们错过了这个。
  • 我想出了一个纯 CSS 的解决方案.. 需要注意的是它只能解决两个丢失的项目,因此只能在每个包装行最多三个项目的弹性网格中安全地工作。 Demo:codepen.io/lukejacksonn/pen/dozqVq这里的原理是使用伪元素作为extra children,并赋予它们与容器中的item相同的flex属性。
  • @Codemonkey 耶稣。我才开始使用 flexbox,想着如何摆脱所有这些旨在将这些内联块对齐网格内的黑客,现在事实证明这根本不可能!我马上就达到了那个障碍,达到了我认为我很难愉快地解决所有这些旧的无法解决的 CSS 问题的极限。没那么快,我猜。只用了 20 年就得到了正确的垂直定心——我们当然可以等待。天啊,这任务似乎太简单了……
  • @dalgard 我不这么认为。见my comment
【解决方案3】:

正如其他海报所提到的 - 没有干净的方法将最后一行与 flexbox 左对齐(至少按照当前规范)

然而,不管它的价值:使用CSS Grid Layout Module,这非常容易产生:

基本上相关代码归结为:

ul {
  display: grid; /* 1 */
  grid-template-columns: repeat(auto-fill, 100px); /* 2 */
  grid-gap: 1rem; /* 3 */
  justify-content: space-between; /* 4 */
}

1) 使容器元素成为网格容器

2) 使用宽度为 100 像素的自动列设置网格。 (注意auto-fill 的使用(与auto-fit 相对) - (对于 1 行布局)将空轨道折叠为 0 - 导致项目扩展以占用剩余空间。这将导致合理的 ' space-between' 布局,当网格只有一行时,这在我们的例子中不是我们想要的。(查看this demo 以了解它们之间的区别)。

3) 为网格行和列设置间隙/间距 - 在这里,因为需要“间距”布局 - 间隙实际上是最小间隙,因为它会根据需要增大。

4) 类似于 flexbox。

ul {
  display: grid;
  grid-template-columns: repeat(auto-fill, 100px);
  grid-gap: 1rem;
  justify-content: space-between;
  
  /* boring properties */
  list-style: none;
  background: wheat;
  padding: 2rem;
  width: 80vw;
  margin: 0 auto;
}

li {
  height: 50px;
  border: 1px solid green;
}
<ul>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

Codepen Demo(调整大小看效果)

【讨论】:

  • 不错的解决方案。唯一的问题是它不适用于 IE10/11。
  • 鉴于当前的可能性,这现在应该是公认的答案。使用:after 伪元素可能会在极端情况下导致不需要的结果。
  • @Danield 这个建议对我帮助很大,谢谢!
  • 这应该是公认的答案。本着渐进增强的精神,我会将它与 flexbox 结合起来作为后备:不支持网格的浏览器将显示 flexbox 版本,这对我来说足够接近。
  • 非常感谢,你拯救了我这一周我一直在寻找这个的一天
【解决方案4】:

没有任何额外的标记,只需添加 ::after 就可以为我指定列的宽度。

.grid {
  display:flex;
  justify-content:space-between;
  flex-wrap:wrap;
}
.grid::after{
  content: '';
  width: 10em // Same width of .grid__element
}
.grid__element{
  width:10em;
}

使用这样的 HTML:

<div class=grid">
   <div class="grid__element"></div>
   <div class="grid__element"></div>
   <div class="grid__element"></div>
</div>

【讨论】:

  • 这很有趣,但并不完全正确。当您处理底行中的两个以上元素时,问题就出现了——上行元素之间出现的间距永远不会出现在最后一行;这些物品被硬包装在一起,否定了空间之间的原始实用性。
  • 如果你使用flex-basis: 10em而不是宽度会更好。
【解决方案5】:

我知道这里有很多答案,但是.. 最简单的方法是使用grid 而不是flexgrid template columns 使用repeatauto fills,您必须在其中设置数字您为每个元素提供的像素数,100px 来自您的 sn-p 代码。

.exposegrid {
     display: grid;
     grid-template-columns: repeat(auto-fill, 100px);
     justify-content: space-between;
}
 .exposetab {
     width: 100px;
     height: 66px;
     background-color: rgba(255, 255, 255, 0.2);
     border: 1px solid rgba(0, 0, 0, 0.4);
     border-radius: 5px;
     box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
     margin-bottom: 10px;
}
<div class="exposegrid">
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
</div>

【讨论】:

  • 这是使最后一行项目左对齐的正确解决方案。
  • 我同意,正确的方法是使用网格。它可以通过 flexbox 实现,但使用网格更简洁。
【解决方案6】:

你不能。 Flexbox 不是网格系统。它没有语言结构来满足您的要求,至少在您使用justify-content: space-between 时不会。与 Flexbox 最接近的是使用列方向,这需要设置显式高度:

http://cssdeck.com/labs/pvsn6t4z(注意:不包括前缀)

ul {
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  height: 4em;
}

但是,只使用列会更简单,它具有更好的支持并且不需要设置特定的高度:

http://cssdeck.com/labs/dwq3x6vr(注意:不包括前缀)

ul {
  columns: 15em;
}

【讨论】:

  • 有办法;看我的回答。
  • @dalgard,您的回答是一种解决方法,而不是真正的解决方案。 cimanon 的答案是正确的。
  • @Jonah 我认为“技术”是对我的回答的公平描述。它确实为很多人提供了解决方案,包括提问者。
  • @dalgard 这并没有改变 Flexbox 不提供语言结构来完成所要求的事情这一事实。此外,我认为添加虚假元素是一种非常肮脏的做法,就像使用表格进行布局一样。
  • 它并不漂亮,但前端开发是可能的艺术;实用主义是一个基本前提。我认为 extremely 这个词用错了,因为在 99.9% 的真实世界网站(参见 Bootstrap 容器元素)上都使用了额外的元素来进行样式设置。
【解决方案7】:

一种可能的解决方案是在.grid 容器上使用justify-content: flex-start;,对其子元素的大小进行限制,并在适当的子元素上使用边距——具体取决于所需的列数。

对于 3 列网格,基本 CSS 如下所示:

.grid {
    display: flex;
    flex-flow: row wrap;
    justify-content: flex-start;
}

.grid > * {
    flex: 0 0 32%;
    margin: 1% 0;
}

.grid > :nth-child(3n-1) {
    margin-left: 2%;
    margin-right: 2%;
}

这是另一个不完美的解决方案,但它确实有效。

http://codepen.io/tuxsudo/pen/VYERQJ

【讨论】:

    【解决方案8】:

    如果您想要一个在项目之间有一些空间的网格,并且项目开始时没有任何初始空间,那么这个简单的解决方案可以工作:

    .grid {
        display: flex;
        flex-flow: row wrap;
        margin: 0 -5px; // remove the inital 5px space
        width: auto;
    }
    .grid__item {
        width: 25%;
        padding: 0 5px; // should be same as the negative margin above.
    }
    

    如果你想要最初的 5px 空间,那么只需删除负边距 :) 简单。

    https://jsfiddle.net/b97ewrno/2/

    公认的答案虽然不错,但它会导致第二行的元素之间没有空格..

    【讨论】:

    • 很惊讶这没有更多的赞成票。这是属于 Flex 博物馆的绝妙方法。
    • @EduardoLaHozMiranda 谢谢!但为什么是“博物馆”? IE11 不支持 CSS 网格,大多数网站仍然需要支持。 + 前端开发中的一些大人物仍然声称网格与网格有不同的用例。弹性盒。但也许你的意思是这应该是网络历史的重要组成部分:D
    • 大声笑,是的。我当时很兴奋。只是意味着这是对这个问题的一个伟大而最小的看法。
    • @dencey 你不需要知道对于这个解决方案,它是 25%,所以每行最多 4 个,但你可以使用任何你想要的百分比
    • @OZZIE 固定项目宽度,而不是百分比,指问题中的样式,期望的效果是项目与两侧的容器边缘对齐,并且每行项目之间的空间相等。 jsfiddle.net/n6k831Ld
    【解决方案9】:

    是的。!我们可以通过一些媒体查询和预定义的最大列数

    这里使用 4 列。检查我的代码:

    .container {
      display: flex;
      display: -webkit-flex;
      display: -moz-flex;
      flex-flow: row wrap;
      -webkit-flex-flow: row wrap;
      -moz-flex-flow: row wrap;
    }
    
    .container .item {
      display: flex;
      display: -webkit-flex;
      display: -moz-flex;
      justify-content: center;
      -webkit-justify-content: center;
      -moz-justify-content: center;
      flex-basis: 25%; //max no of columns in %, 25% = 4 Columns
    }
    
    .container .item .item-child {
      width: 130px;
      height: 180px;
      background: red;
      margin: 10px;
    }
    
    @media (max-width: 360px) {
      .container .item {
        flex-basis: 100%;
      }
    }
    
    @media (min-width:360px) and (max-width: 520px) {
      .container .item {
        flex-basis: 50%;
      }
    }
    
    @media (min-width:520px) and (max-width: 680px) {
      .container .item {
        flex-basis: 33.33%;
      }
    }
    <div class="container">
    
      <div class="item">
        <div class="item-child">1</div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
      <div class="item">
        <div class="item-child"></div>
      </div>
    
    </div>

    注意
    1)无需创建子div。它可以是任何其他标签,如 'img' r 无论你想要什么..
    2)如果您想要更多列,请调整媒体查询和最大列数。

    【讨论】:

    • 这只会在最新的 IE 中创建 3 个
    【解决方案10】:

    使用 CSS 网格为我解决了这个问题,

    此解决方案仅适用于您拥有固定数量的列,即否。在一行中显示的元素数

    -> 使用网格但不指定行数,随着元素数量的增加,它会换行并动态添加行,我在此示例中指定了三列

    ->您不必为您的孩子/单元格提供任何位置,因为它会修复它,这是我们不想要的。

    .grid-class{
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      column-gap: 80px;
    }

    【讨论】:

    • 这对我来说是最好的解决方案!
    【解决方案11】:

    如果要将最后一项与网格对齐,请使用以下代码:

    网格容器

    .card-grid {
      box-sizing: border-box;
      max-height: 100%;
      display: flex;
      flex-direction: row;
      -webkit-box-orient: horizontal;
      -webkit-box-direction: normal;
      justify-content: space-between;
      align-items: stretch;
      align-content: stretch;
      -webkit-box-align: stretch;
      -webkit-box-orient: horizontal;
      -webkit-box-direction: normal;
      -ms-flex-flow: row wrap;
      flex-flow: row wrap;
    }
    
    .card-grid:after {
      content: "";
      flex: 1 1 100%;
      max-width: 32%;
    }
    

    网格中的项目

    .card {
      flex: 1 1 100%;
      box-sizing: border-box;
      -webkit-box-flex: 1;
      max-width: 32%;
      display: block;
      position: relative;
    
    }
    

    诀窍是将项目的最大宽度设置为等于 .card-grid:after 的最大宽度。

    Live demo on Codepen

    【讨论】:

    • cthulu 祝福你和你的电脑
    • 当卡片大小固定且每行卡片数量未知时,此方法不起作用。 codepen.io/zendu/pen/WXNGvo
    【解决方案12】:

    你也可以这样做:

    .exposegrid:last-child {
      margin-right: auto;
    }
    

    【讨论】:

      【解决方案13】:

      可以使用“flex-start”并手动添加边距。它需要一些数学技巧,但绝对很容易做到,并且可以很容易地与像 LESS 这样的 CSS 预处理器一起使用。

      例如看这个LESS mixin:

      .flexboxGridMixin(@columnNumber,@spacingPercent) {
        @contentPercent: 100% - @spacingPercent;
        @sideMargin: @spacingPercent/(@columnNumber*2);
        display: flex;
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: flex-start;
        > * {
          box-sizing: border-box;
          width: @contentPercent/@columnNumber;
          margin-left: @sideMargin;
          margin-right: @sideMargin;
        }
      }
      

      然后它可以很容易地用于显示响应式网格布局:

      ul {
        list-style: none;
        padding: 0;
        @spacing: 10%;
        @media only screen and (max-width: 499px) { .flexboxGridMixin(1,@spacing); }
        @media only screen and (min-width: 500px) { .flexboxGridMixin(2,@spacing); }
        @media only screen and (min-width: 700px) { .flexboxGridMixin(3,@spacing); }
        @media only screen and (min-width: 900px) { .flexboxGridMixin(4,@spacing); }
        @media only screen and (min-width: 1100px) { .flexboxGridMixin(5,@spacing); }
      }
      
      li {
        background: pink;
        height: 100px;
        margin-top: 20px;
      }
      

      这是一个例子

      http://codepen.io/anon/pen/YyLqVB?editors=110

      【讨论】:

      • 你从不使用@contentPercent。你打算这样做吗?
      • 宽度:@contentPercent/@columnNumber;
      • 哇!这个解决方案给我留下了深刻的印象。我会尽量适应我的情况
      【解决方案14】:

      这是很多答案的组合,但它完全符合我的需要——也就是说,将 flex 容器中的最后一个子元素向左对齐,同时保持间隔行为(在这种情况下,它是三列布局)。

      这是标记:

      .flex-container {
        display: flex;
        justify-content: space-between;
        flex-direction: row;
      }
      
      .flex-container:after {
        content: "";
        flex-basis: 30%;
      }
      

      【讨论】:

      • 更通用:flex-basis size 必须等于 child 的 size。
      • 我发现 flex-grow: 0.9 而不是 flex-basis 适用于任意数量的列。在一堆现代浏览器中测试 - 它适用于所有浏览器,但填充在 IE 中被破坏(但在 Edge0 中工作
      【解决方案15】:

      如果您希望网格视图中的项目与最后一个元素的距离相等。确保您的卡片宽度为 100% 使用以下 CSS。这很好用

      .container {
        /* ... snip ... */
        display: grid;
        grid-template-columns: repeat(auto-fill, 100px);
        justify-content: space-between;
        grid-gap: 20px;
      }
      

      【讨论】:

        【解决方案16】:

        这个版本最适合固定宽度的块:

        http://codepen.io/7iomka/pen/oxxeNE

        在其他情况下 - dalgard 的版本

        http://codepen.io/dalgard/pen/Dbnus

        body {
          padding: 5%;
        }
        
        div {
          overflow: hidden;
          background-color: yellow;
        }
        
        ul {
          display: flex;
          flex-wrap: wrap;
        justify-content:center;
          margin: 0 -4px -4px 0;
          list-style: none;
          padding: 0;
        }
        
        li {
          flex: 1 0 200px;
          height: 200px;
          max-width:200px;
          min-width:200px;
          border-right: 4px solid black;
          border-bottom: 4px solid black;
          background-color: deeppink;
        }
        li:empty {
          height: 0;
          border: none;
        }
        
        *,
        :before,
        :after {
          box-sizing: border-box;
        }
        <div>
          <ul>
            <li>a</li>
            <li>b</li>
            <li>c</li>
            <li>d</li>
            <li>e</li>
            <li>f</li>
            <li>g</li>
            <li>h</li>
            <li>i</li>
            <li>j</li>
            <li>k</li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
            <li></li>
          </ul>
        </div>

        【讨论】:

          【解决方案17】:

          只需添加几个具有相同属性的假项目,除了高度设置为 0px 到最后。

          【讨论】:

          • 添加假货在各个方面都是不好的做法。除非是强制性的,否则您不应该仅仅为了破解 css 而在 DOM 中填充东西。出于许多原因,从可访问性,到用奇怪的东西充斥代码库,再到使逻辑更复杂,难以理解,并且继续列出。除非您明确表示这可能是一个糟糕的解决方案或有特殊情况,否则不要推荐 hack。
          • @Eksapsy 好吧,我找不到任何解决方案在 100% 的情况下工作且不使用 javascript。使用 javascript 会使事情变得更加复杂。网格+列模板?也许它也必须在 IE11 中工作,所以不。 nth-child、last-child、'after' 说明符......这些都不适用于特定场景。有时除了使用丑陋的代码或较低的设计要求之外别无他法。
          • 有趣的是,这实际上是唯一可行的解​​决方案(除了 JS-hacking),它有 0 票。嗯……不再了!无论如何,您需要添加的空 div 的数量是 N - 1,其中 N 是一行中的最大项目数。请注意,此解决方案允许容器将 space-around、space-between 和 space-evenly 用于其 justify-content 属性。最好将空 div 设置为 flex: 0 0 nn 其中 nn 与真实元素具有相同的 flex-basis。
          【解决方案18】:

          即使 Flexbox 出现了差距,我也会添加一个可行的解决方案。

          它使用兄弟组合器来检查 2 个条件。

          它检查的第一个条件是元素是否是倒数第二个div:nth-last-child(2)

          对于 4 列布局,我们需要检查位置 2 和 3 检查它是否在 4 的第二行 div:nth-of-type(4n+2) 或第三行 div:nth-of-type(4n+3)

          对于 3 列布局,我们只需要检查位置 2

          div:nth-of-type(3n+2)
          

          然后我们可以像下面这样组合 4 列布局

          div:nth-last-child(2) + div:nth-of-type(4n+2)
          
          div:nth-last-child(2) + div:nth-of-type(4n+3)
          

          我们还需要处理一个边缘情况,任何 3n+2 和 4 的倍数的数都将获得 35% 的边距右div:nth-last-child(2) + div:nth-of-type(4n+4)

          3 列布局将是

          div:nth-last-child(2) + div:nth-of-type(3n+2)
          

          然后我们需要给上面的选择器添加一个边距。需要计算 margin-right 并且取决于 flex-basis。

          我添加了一个包含 3 列和 4 列的示例以及一个媒体查询。我还添加了一个小的 JavaScript 按钮,用于添加一个新的 div,以便您检查它是否有效。

          这是一点点 CSS,但它可以工作。 如果您需要更多解释,我也在我的网站上写过这个。 https://designkojo.com/css-programming-using-css-pseudo-classes-and-combinators

          var number = 11;
          
          $("#add").on("click", function() {
              number = number + 1;
              $("#main").append("<div>" + number + "</div>");
          });
          body {
            margin: 0;
          }
          main{
            display: flex;
            flex-wrap: wrap;
            align-items: flex-start;
            align-content: flex-start; /* vertical */
            justify-content: space-between;
            min-width: 300px;
            max-width: 1200px;
            margin: 20px auto;
            background-color: lightgrey;
            height: 100vh;
          }
          div {
            flex-basis: 30%;
            background-color: #5F3BB3;
            min-height: 20px;
            height: 50px;
            margin-bottom: 20px;
            display: flex;
            justify-content: center;
            align-items: center;
            color: #9af3ff;
            font-size: 3em;
          }
          
          
          div:nth-last-child(2) + div:nth-of-type(3n+2) {
            background-color: #f1b73e;
            margin-right: 35%;
          }
          
          @media screen and (min-width: 720px) {
          
            div {
              flex-basis: 22%;
            }
          
            div:nth-last-child(2) {
              background-color: greenyellow;
            }
          
            div:nth-of-type(4n+2) {
              background-color: deeppink;
            }
          
            /* Using Plus combinator is for direct sibling */
            div:nth-last-child(2) + div:nth-of-type(4n+2) {
              background-color: #f1b73e;
              margin-right: 52%;
            }
          
            div:nth-last-child(2) + div:nth-of-type(4n+3) {
              background-color: #f1b73e;
              margin-right: 26%;
            }
          
            /* Also need to set the last to 0% to override when it become (3n+2)
             * Any number that is 3n+2 & multiple of 4 will get the 35% margin-right
             * div:nth-last-child(2) + div:nth-of-type(3n+2)
             */
          
            div:nth-last-child(2) + div:nth-of-type(4n+4) {
              background-color: #f1b73e;
              margin-right: 0;
            }
          
          }
          <!DOCTYPE html>
          <html lang="en">
          
          <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <link rel="stylesheet" href="style.css">
            <title>My New Project</title>
          </head>
          
          <body>
          
          <header>
          
          
          </header>
          
          <button id="add">Add</button>
          <main id="main">
          
            <div>1</div>
            <div>2</div>
            <div>3</div>
            <div>4</div>
            <div>5</div>
            <div>6</div>
            <div>7</div>
            <div>8</div>
            <div>9</div>
            <div>10</div>
            <div>11</div>
          
          
          </main>
          <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
          <script src="action.js"></script>
          </body>
          </html>

          【讨论】:

            【解决方案19】:

            虽然您需要满足以下条件,但有一种方法可以不使用 flexbox。 1)容器有填充物。 2) 项目大小相同,您确切知道每行需要多少个。

            ul {
              padding: 0 3% 0 5%;
            }
            li {
              display: inline-block; 
              padding: 0 2% 2% 0;
              width: 28.66%;
            }
            

            容器右侧较小的填充允许每个列表项右侧的额外填充。假设与列表对象相同的父项中的其他项用 0 5% 填充,它将与它们齐平。您还可以将百分比调整为您想要的边距或使用计算 px 值。

            当然,您可以通过使用 nth-child (IE 9+) 删除容器上的边距来执行相同的操作,而无需容器上的填充。

            【讨论】:

              【解决方案20】:

              使用 flexbox 和一些媒体查询,我做了一个小变通方法:http://codepen.io/una/pen/yNEGjv(它有点 hacky 但有效):

              .container {
                display: flex;
                flex-flow: row wrap;
                justify-content: flex-start;
                max-width: 1200px;
                margin: 0 auto;
              }
              
              .item {
                background-color: gray;
                height: 300px;
                flex: 0 30%;
                margin: 10px;
              
                @media (max-width: 700px) {
                   flex: 0 45%;
                }
              
                @media (max-width: 420px) {
                  flex: 0 100%;
                }
              
                &:nth-child(3n-1) {
                  margin-left: 10px;
                  margin-right: 10px;
                }
              }
              

              【讨论】:

                【解决方案21】:

                我为它做了一个 SCSS mixin。

                @mixin last-row-flexbox($num-columns, $width-items){
                
                  $filled-space: $width-items * $num-columns;
                  $margin: calc((100% - #{$filled-space}) / (#{$num-columns} - 1));
                
                  $num-cols-1 : $num-columns - 1;
                
                  &:nth-child(#{$num-columns}n+1):nth-last-child(-n+#{$num-cols-1}) ~ & {
                    margin-left: $margin;
                  }
                  @for $i from 1 through $num-columns - 2 { 
                    $index: $num-columns - $i;
                    &:nth-child(#{$num-columns}n+#{$index}):last-child{
                      margin-right: auto;
                    }
                  }
                }
                

                这是codepen链接:http://codepen.io/diana_aceves/pen/KVGNZg

                您只需以百分比和列数设置项目宽度。

                希望对你有帮助。

                【讨论】:

                  【解决方案22】:

                  这是另外几个 scss mixin。

                  这些 mixin 假定您不会使用 Isotope 之类的 js 插件(它们不尊重 html 标记顺序,因此会混淆 css nth 规则)。

                  此外,您将能够充分利用它们,尤其是当您以移动优先方式编写响应式断点时。理想情况下,您将在较小的断点上使用 flexbox_grid() 并在以下断点上使用 flexbox_cell()。 flexbox_cell() 将负责重置以前设置的边距,不再用于较大的断点。

                  顺便说一句,只要您正确设置了容器的 flex 属性,如果需要,您也可以只对项目使用 flexbox_cell()。

                  代码如下:

                  // apply to the container (for ex. <UL> element)
                  @mixin flexbox_grid($columns, $gutter_width){
                  
                    display: flex;
                    flex-direction:row;
                    flex-wrap:wrap;
                    justify-content: flex-start;
                  
                    > *{
                      @include flexbox_cell($columns, $gutter_width);
                    }
                  }
                  
                  // apply to the cell (for ex. a <LI> element)
                  @mixin flexbox_cell($columns, $gutter_width){
                    $base_width: 100 / $columns;
                    $gutters: $columns - 1;
                    $gutter_offset: $gutter_width * $gutters / $columns;
                  
                    flex-grow: 0;
                    flex-shrink: 1;
                    flex-basis: auto; // IE10 doesn't support calc() here
                  
                    box-sizing:border-box; // so you can freely apply borders/paddings to items
                    width: calc( #{$base_width}% - #{$gutter_offset} );
                  
                    // remove useless margins (for cascading breakponts)
                    &:nth-child(#{$columns}n){
                      margin-right: 0;
                    }
                  
                    // apply margin
                    @for $i from 0 through ($gutters){
                      @if($i != 0){
                        &:nth-child(#{$columns}n+#{$i}){
                          margin-right: $gutter_width;
                        }
                      }
                    }
                  }
                  

                  用法:

                  ul{
                     // just this:
                     @include flexbox_grid(3,20px);
                  }
                  
                  // and maybe in following breakpoints, 
                  // where the container is already setted up, 
                  // just change only the cells:
                  
                  li{
                     @include flexbox_cell(4,40px);
                  }
                  

                  显然,最终由您来设置容器的填充/边距/宽度和单元格的底部边距等。

                  希望对你有帮助!

                  【讨论】:

                    【解决方案23】:

                    这很 hacky,但它对我有用。我试图实现一致的间距/边距。

                    .grid {
                      width: 1024px;
                      display: flex;
                      flex-flow: row wrap;
                      padding: 32px;
                      background-color: #ddd;  
                    
                      &:after {
                        content: "";
                        flex: auto;
                        margin-left:-1%;
                      }
                    
                      .item {
                        flex: 1 0 24.25%;
                        max-width: 24.25%;
                        margin-bottom: 10px;
                        text-align: center;
                        background-color: #bbb;
                    
                        &:nth-child(4n+2),
                        &:nth-child(4n+3),
                        &:nth-child(4n+4) {
                          margin-left: 1%;
                        }
                    
                        &:nth-child(4n+1):nth-last-child(-n+4),
                          &:nth-child(4n+1):nth-last-child(-n+4) ~ .item {
                            margin-bottom: 0;
                        }    
                    
                      }
                    }
                    

                    http://codepen.io/rustydev/pen/f7c8920e0beb0ba9a904da7ebd9970ae/

                    【讨论】:

                      【解决方案24】:

                      似乎没有人在最后一项上提出 flex-grow 解决方案。 这个想法是让你的最后一个弹性项目占据它可以使用 flex-grow: 1 的所有位置。

                      .grid {
                        display: flex;
                        flex-flow: row wrap;
                        justify-content: space-between;
                      }
                      
                      .grid > *:last-child {
                        flex-grow: 1;
                      }
                      

                      注意:这个解决方案并不完美,特别是如果您的弹性项目中有居中元素,因为它会以可能巨大的最后一个弹性项目为中心。

                      【讨论】:

                        【解决方案25】:

                        天哪,我想我找到了一个用最少的 CSS 和没有 JS 的好解决方案。看看吧:

                        img {width:100%;}
                        li {
                          display: inline-block;
                          width:8em;
                          list-style:none;
                        }
                        ul {text-align: justify;}
                        <ul>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li>
                            <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
                          </li>
                          <li></li>
                          <li></li>
                          <li></li>
                          <li></li>
                          <li></li>
                          <li></li>
                          <li></li>
                        </ul>

                        这里的关键是要记住,我们正在努力实现的目标正是 text-align: justify 所做的!

                        HTML 中的空元素可以在不改变外观的情况下完美显示最后一行,但考虑到您想要实现的目标,可能不需要。为了在每种情况下达到完美平衡,您至少需要 x-4 个空元素,x 是要显示的元素数,或者 n-2,n 是要显示的列数。

                        【讨论】:

                          【解决方案26】:

                          假设:

                          • 您想要带环绕的 4 列网格布局
                          • 项数不一定是4的倍数

                          为每个项目设置左边距,除了第 1、5 和 9 个项目等。如果左边距为 10px,则每行将有 30px 的边距分布在 4 个项目中。 item 的百分比宽度计算如下:

                          100% / 4 - horizontal-border - horizontal-padding - left-margin * (4 - 1) / 4
                          

                          对于涉及弹性盒最后一行的问题,这是一个不错的解决方法。

                          .flex {
                            display: flex;
                            flex-direction: row;
                            flex-wrap: wrap;
                            margin: 1em 0 3em;
                            background-color: peachpuff;
                          }
                          
                          .item {
                            margin-left: 10px;
                            border: 1px solid;
                            padding: 10px;
                            width: calc(100% / 4 - 2px - 20px - 10px * (4 - 1) / 4);
                            background-color: papayawhip;
                          }
                          
                          .item:nth-child(4n + 1) {
                            margin-left: 0;
                          }
                          
                          .item:nth-child(n + 5) {
                            margin-top: 10px;
                          }
                          <div class="flex">
                            <div class="item">1</div>
                            <div class="item">2</div>
                            <div class="item">3</div>
                            <div class="item">4</div>
                          </div>
                          <div class="flex">
                            <div class="item">1</div>
                            <div class="item">2</div>
                            <div class="item">3</div>
                            <div class="item">4</div>
                            <div class="item">5</div>
                            <div class="item">6</div>
                          </div>
                          <div class="flex">
                            <div class="item">1</div>
                            <div class="item">2</div>
                            <div class="item">3</div>
                            <div class="item">4</div>
                            <div class="item">5</div>
                            <div class="item">6</div>
                            <div class="item">7</div>
                            <div class="item">8</div>
                            <div class="item">9</div>
                          </div>

                          【讨论】:

                            【解决方案27】:

                            如果您知道行中元素之间的空格宽度和行中元素的数量,这将起作用:

                            示例:一行 3 个元素,元素之间的间距为 10px

                            div:last-child:nth-child(3n+2) {
                              flex-grow: 1
                              margin-left: 10px
                            }
                            

                            【讨论】:

                              【解决方案28】:

                              我修改了 Dan Andreasson 提出的示例,通过在元素上使用右边框来创建人造排水沟。然后,您可以使用 nth-child 删除您需要的列网格计数的最后一个子项上的边框。这是一个演示https://codepen.io/JacobLett/pen/mdVoroM

                              /* demo only */
                              body {
                              margin:0;
                              padding:0;
                              max-width:1024px;
                              margin:0 auto;
                              }
                              .block-list {
                              background: #ccc;
                                border:1px solid #ccc;
                              }
                              
                              .block-list .block-list__item {
                              background: #eee;
                              }
                              /* demo only */
                              
                              
                              
                              
                              .block-list .block-list__item {
                                 min-height: 100px;
                                 margin-bottom: 1rem;
                              }
                              
                              @media only screen and (min-width: 900px) {
                                 .block-list {
                                    display: -webkit-box;
                                    display: flex;
                                    flex-wrap: wrap;
                                    -webkit-box-pack: justify;
                                    justify-content: space-between;
                                    background-color: #ffffff;
                                    margin: 1em auto;
                                 }
                              
                                 .block-list:after {
                                    content: "";
                                    -webkit-box-flex: 1;
                                    flex: auto;
                                 }
                              
                                 .block-list__item {
                                    height: 10em;
                                    width: 25%;
                                    box-sizing: border-box;
                                    border-right: 10px solid white;
                                 }
                              
                                 .block-list-2 .block-list__item {
                                    width: 50%;
                                 }
                              
                                 .block-list-2 .block-list__item:nth-child(2n) {
                                    border: none;
                                 }
                              
                                 .block-list-3 .block-list__item {
                                    width: 33.3%;
                                 }
                              
                                 .block-list-3 .block-list__item:nth-child(3n) {
                                    border: none;
                                 }
                              
                                 .block-list-4 .block-list__item {
                                    width: 25%;
                                 }
                              
                                 .block-list-4 .block-list__item:nth-child(4n) {
                                    border: none;
                                 }
                                 
                                 .block-list-5 .block-list__item {
                                    width: 20%;
                                 }
                              
                                 .block-list-5 .block-list__item:nth-child(5n) {
                                    border: none;
                                 }
                                 
                                 .block-list-6 .block-list__item {
                                    width: 16.66%;
                                 }
                              
                                 .block-list-6 .block-list__item:nth-child(6n) {
                                    border: none;
                                 }
                              }
                              <h2>2 column</h2>
                              <div class="block-list block-list-2">
                                 <div class="block-list__item">1
                                 </div>
                                 <div class="block-list__item">2
                                 </div>
                                 <div class="block-list__item">3
                                 </div>
                                 <div class="block-list__item">4
                                 </div>
                                 <div class="block-list__item">5
                                 </div>
                                 <div class="block-list__item">6
                                 </div>
                              </div>
                              <h2>3 column</h2>
                              <div class="block-list block-list-3">
                                 <div class="block-list__item">1
                                 </div>
                                 <div class="block-list__item">2
                                 </div>
                                 <div class="block-list__item">3
                                 </div>
                                 <div class="block-list__item">4
                                 </div>
                                 <div class="block-list__item">5
                                 </div>
                                 <div class="block-list__item">6
                                 </div>
                              </div>
                              
                              <h2>4 column</h2>
                              <div class="block-list block-list-4">
                                 <div class="block-list__item">1
                                 </div>
                                 <div class="block-list__item">2
                                 </div>
                                 <div class="block-list__item">3
                                 </div>
                                 <div class="block-list__item">4
                                 </div>
                                 <div class="block-list__item">5
                                 </div>
                                 <div class="block-list__item">6
                                 </div>
                              </div>
                              <h2>5 column</h2>
                              <div class="block-list block-list-5">
                                 <div class="block-list__item">1
                                 </div>
                                 <div class="block-list__item">2
                                 </div>
                                 <div class="block-list__item">3
                                 </div>
                                 <div class="block-list__item">4
                                 </div>
                                 <div class="block-list__item">5
                                 </div>
                                 <div class="block-list__item">6
                                 </div>
                              </div>
                              <h2>6 column</h2>
                              <div class="block-list block-list-6">
                                 <div class="block-list__item">1
                                 </div>
                                 <div class="block-list__item">2
                                 </div>
                                 <div class="block-list__item">3
                                 </div>
                                 <div class="block-list__item">4
                                 </div>
                                 <div class="block-list__item">5
                                 </div>
                                 <div class="block-list__item">6
                                 </div>
                              </div>

                              【讨论】:

                                【解决方案29】:

                                如果单个子项具有明确的宽度(例如 32%),您可以通过向父项添加 :after 元素并赋予其相同的明确宽度来解决此问题。

                                【讨论】:

                                  【解决方案30】:

                                  这里有一些解决方案,人们建议编写精确的布局 css 类、使用伪元素伪造最后一项、使用非 flexbox 方法等。

                                  一个大问题是邻居之间的差距(大小写对齐的按钮换行到多行)。在这种情况下,您不希望项目相互接触,需要有间隙。我只想添加一个尊重差距并适用于任意数量项目的采用性解决方案。虽然它也是基于假最后一个元素的想法,但更普遍。有关详细信息,请参阅 sn-p cmets。

                                  html {
                                    font-size: 1px;
                                  }
                                  
                                  .container {
                                    font-size: 16rem;
                                    display: flex;
                                    flex-wrap: wrap;
                                    justify-content: space-between;
                                  }
                                  
                                  .item {
                                    background-color: orange;
                                    border-radius: 10rem;
                                    box-sizing: border-box;
                                    color: white;
                                    margin-bottom: 10rem;
                                    padding: 15rem 10rem;
                                    text-align: center;
                                  }
                                  <!--
                                  Our setup from design (example) used later in calculations:
                                  
                                  container-width: 100%; (can be any)
                                  max-per-row = 4;
                                  total = 6;
                                  desired-hor-gap = 10rem; (equal to vert. gap)
                                  
                                  If you go dynamic (drawing html according to the coming data either in a backend template or in a frontend template), you have to calculate and then set exact properties inline.
                                  
                                  <i> (or any real html element) is needed to set inline styles to arrange the last row properly.
                                  
                                  "2" in <i> calc function - is 6 % 4 since calc doesn't allow for "%" operator. But in real life you will calculate these numbers in JS or some backend template anyway.
                                  
                                     Formulas written in elements' calc functions. Seem to be self-descriptive, but the idea is to set for the last fake item the remainder width + hypothetical gaps.
                                  -->
                                  
                                  <div class="container">
                                  
                                  <div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
                                  <div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
                                  <div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
                                  <div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
                                  <div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
                                  <div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
                                  
                                  <i style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4 * (4 - 2) + ( 4 - 2 - 1) * 10rem);"></i>
                                  </div>

                                  【讨论】:

                                    猜你喜欢
                                    • 2015-11-19
                                    • 1970-01-01
                                    • 1970-01-01
                                    相关资源
                                    最近更新 更多