【问题标题】:Flexbox wrapping nested rows without media query没有媒体查询的 Flexbox 包装嵌套行
【发布时间】:2018-01-24 12:39:31
【问题描述】:

我在 flexbox 网格中有四个 div。我希望它们一次包装两个,如下所示:

+-----------------------+
|  1  |  2  |  3  |  4  | 
+-----------------------+
+-----------+
|  1  |  2  |
+-----------+    THIS IS WHAT I WANT
|  3  |  4  |
+-----------+
+-----+
|  1  |
+-----+
|  2  |
+-----+
|  3  |
+-----+
|  4  |
+-----+

现在,这似乎很简单,只需将它们嵌套在新的 flex 容器中并应用 flex-wrap,并给单元格一些最小宽度。但是,这样做的副作用是使中间视图看起来像这样:

+-----------+
|  1  |  3  |
+-----------+    NOT WHAT I WANT
|  2  |  4  |
+-----------+

显然,flexbox 想要首先包装内部 div,而不是考虑它们的行。为了保持所有其他包装工作,为嵌套 div 设置 flex-basis(例如 100%)不是一个选项。为了保持一切动态(例如,将第三个单元格添加到其中一行),在单元格上设置 %-widths 不是一种选择。为了避免硬断点和基于(动态)内容宽度的基础换行,我真的希望避免媒体查询。

这可以通过 flexbox 实现而不需要媒体查询吗?

JSFiddle

div {
  box-sizing: border-box;
  margin: 2px;
}

.grid {
  display: flex;
  flex-flow: row wrap;
  border: 2px solid blue;
  flex: 1;
}

.cell {
  flex: 1;
  min-width: 100px;
  border: 2px solid red;
  background: white;
  height: 100px;
}
<div class="grid">
  <div class="grid">
    <div class="cell">1</div>
    <div class="cell">2</div>
  </div>
  <div class="grid">
    <div class="cell">3</div>
    <div class="cell">4</div>
  </div>
</div>

编辑:我知道我可以让内部.grid 根本不换行,但我真正想要的是如果空间非常紧张,所有单元格都可以在彼此下方换行。 (如第一张插图。)

【问题讨论】:

  • 我再次更新了我的答案,提供了更多解释和最佳解决方案示例

标签: html css flexbox


【解决方案1】:

你需要告诉.grid .grid的子元素连续流动:

div {
  box-sizing: border-box;
  margin: 2px;
}

.grid {
  display: flex;
  flex-flow: row wrap;
  border: 2px solid blue;
  flex: 1;
}

.grid .grid {
  flex-flow: row; /* this is your fix */
}

.cell {
  flex: 1;
  min-width: 100px;
  border: 2px solid red;
  background: white;
  height: 100px;
}
<div class="grid">
  <div class="grid">
    <div class="cell">1</div>
    <div class="cell">2</div>
  </div>
  <div class="grid">
    <div class="cell">3</div>
    <div class="cell">4</div>
  </div>
</div>

【讨论】:

  • 解释一下为什么你的解决方案有效可能很好:当你声明flex-flow: row 时,flex-wrap 属性没有在简写中声明。这意味着它将回退到默认值 nowrap,这会防止嵌套网格的元素换行。
  • 这使得内部网格flex-wrap: initial (=nowrap)。反过来,这意味着最后一个(最窄的)视图不换行,即我修复了一个问题但又创建了另一个问题。
【解决方案2】:

请注意,没有特定的 Flexbox 属性可以替代媒体查询,也没有必要,因为媒体查询非常适合这一点,比任何其他可用的方法或属性都好。

这里的诀窍是让 inner grid's 在cell's 之前换行。为此,它们还需要一个最小宽度,该宽度大于 2 个cell 的总和。

额外的min-width 的缺点是它也会影响cell 在较窄屏幕上的宽度

Fiddle demo 1

堆栈sn-p

div {
  box-sizing: border-box;
  margin: 2px;
}
.grid-outer {
  display: flex;
  flex-wrap: wrap;
  border: 2px solid blue;
}
.grid-inner {
  flex: 1;
  display: inline-flex;
  flex-wrap: wrap;
  border: 2px solid blue;
  min-width: 210px;
}
.cell {
  flex: 1;
  min-width: 100px;
  border: 2px solid red;
  background: white;
  height: 100px;
}
<div class="grid-outer">
  <div class="grid-inner">
    <div class="cell">1</div>
    <div class="cell">2</div>
  </div>
  <div class="grid-inner">
    <div class="cell">3</div>
    <div class="cell">4</div>
  </div>
</div>

一个选项是将 Flexbox 属性放在 outer grid 并将 inner grid's 设置为 inline-flex 并让 cell s 与他们的内容一起成长。

这样做的缺点是cell 不会填满他们父母的宽度

Fiddle demo 2

堆栈sn-p

div {
  box-sizing: border-box;
  margin: 2px;
}
.grid-outer {
  display: inline-block;
}
.grid-inner {
  display: inline-flex;
  flex-wrap: wrap;
  border: 2px solid blue;
}
.cell {
  flex: 1;
  min-width: 100px;
  border: 2px solid red;
  background: white;
  height: 100px;
}
<div class="grid-outer">
  <div class="grid-inner">
    <div class="cell">1</div>
    <div class="cell">2</div>
  </div>
  <div class="grid-inner">
    <div class="cell">3</div>
    <div class="cell">4</div>
  </div>
</div>

这里绝对最好的解决方案是 Flexbox 和媒体查询的组合,其中使用查询将 outer grid 的 flex 方向更改为列...

Fiddle demo

堆栈sn-p

div {
  box-sizing: border-box;
  margin: 2px;
}
.grid-outer {
  display: flex;
  border: 2px solid blue;
}
.grid-inner {
  flex: 1;
  display: flex;
  border: 2px solid blue;
}
.cell {
  flex: 1;
  min-width: 100px;
  border: 2px solid red;
  background: white;
  height: 100px;
}

@media (max-width: 600px) {
  .grid-outer {
    flex-direction: column;
  }
}
<div class="grid-outer">
  <div class="grid-inner">
    <div class="cell">1</div>
    <div class="cell">2</div>
  </div>
  <div class="grid-inner">
    <div class="cell">3</div>
    <div class="cell">4</div>
  </div>
</div>

...或将 inner grid 全部放在一起并更改 cell 的弹性基础

Fiddle demo

堆栈sn-p

div {
  box-sizing: border-box;
  margin: 2px;
}
.grid-outer {
  display: flex;
  flex-wrap: wrap;
  border: 2px solid blue;
}
.cell {
  flex: 1;
  min-width: 100px;
  border: 2px solid red;
  background: white;
  height: 100px;
}

@media (max-width: 600px) {
  .cell {
    flex-basis: calc(50% - 4px);
  }
}
<div class="grid-outer">
    <div class="cell">1</div>
    <div class="cell">2</div>
    <div class="cell">3</div>
    <div class="cell">4</div>
</div>

【讨论】:

    【解决方案3】:

    对网格有不同的定义就可以了。我将它们重新定义为外部和内部网格。

    编辑:为 .grid-inner 添加了换行以覆盖宽度

    div {
      box-sizing: border-box;
      margin: 2px;
    }
    
    .grid-outer {
      display: flex;
      flex-flow: row wrap;
      border: 2px solid blue;
      flex: 1;
      width: 230px; /* for demo purposes */
    }
    
    .grid-inner {
      display: flex;
      border: 2px solid green;
      flex-wrap: wrap;
    }
    
    .cell {
      flex: 1;
      min-width: 100px;
      border: 2px solid red;
      background: white;
      height: 100px;
    }
    <div class="grid-outer">
      <div class="grid-inner">
        <div class="cell">1</div>
        <div class="cell">2</div>
      </div>
      <div class="grid-inner">
        <div class="cell">3</div>
        <div class="cell">4</div>
      </div>
    </div>

    【讨论】:

    • 再次,与 Gerrit 提出的答案相同的问题 - 内部 div 根本不换行,这是宽度为
    • 这简直太棒了。 :) 需要注意的是细胞根本不会生长(最后一个单列情况除外)。
    猜你喜欢
    • 2013-04-13
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    • 2019-01-17
    • 2015-07-18
    • 2014-02-19
    • 2018-06-14
    • 1970-01-01
    相关资源
    最近更新 更多