【问题标题】:Have certain items stack along the cross axis within a row/column of a flex layout with only CSS在仅使用 CSS 的 flex 布局的行/列中沿横轴堆叠某些项目
【发布时间】:2015-05-27 17:17:58
【问题描述】:

在某一时刻,我正在玩弄一个 CSS 规范建议,但后来我想可能已经有一个我缺少的解决方案。我正在谈论的布局示例如下所示:

+-----------+---+
|     1     | 6 |
+---+---+---+   |
| 2 | 3 | 4 +---+
+---+---+---+ 7 |
|     5     |   |
+-----------+---+

问题是左列中间的那三个框是沿交叉轴堆叠的,我在 CSS 中找不到这样做的机制。我知道这可以通过将 div 包裹在行方向 flex 布局的这 3 个项目周围来完成,但这种方法破坏了 flex 布局的灵活性,因为这些项目不能再围绕外部布局和列重新排序/他们之间不能再发生换行。那么,如何仅使用 CSS 来实现这一点,让 flex 布局保持灵活?

HTML:

<div id="flex-layout">
<div id="item1">1</div>
<div id="item2">2</div>
<div id="item3">3</div>
<div id="item4">4</div>
<div id="item5">5</div>
<div id="item6">6</div>
<div id="item7">7</div>
</div>

CSS:

#flex-layout {
    display: flex;
    flex-direction: column;
    height: 300px;
    width: 400px;
    flex-wrap: wrap;
    align-items: stretch;
}

#item1 {
    flex: 0 0 100px;
    width: 300px;
}

#item2 {
    flex: 0 0 100px;
    width: 100px;
}

#item3 {
    flex: 0 0 100px;
    width: 100px;
}

#item4 {
    flex: 0 0 100px;
    width: 100px;
}

#item5 {
    flex: 0 0 100px;
}

#item6 {
    flex: 0 0 150px;
    width: 100px;
}

#item7 {
    flex: 0 0 150px;
}

【问题讨论】:

  • 你能展示一下你到目前为止写的东西吗?
  • 这只是一个假设案例的模型,但我为它添加了一些代码。
  • 如果您不介意将 6 和 7 放在另一个 flex 容器中,您可以使用行布局。
  • @Oriol 我知道这也是一个选项,但我想完全避免编辑 HTML 以保留 flex 布局的精神,否则这似乎是当前的 flex 布局规范。如果它实际上是当前规范中的一个缺点,那么我有一个想法可以解决这个缺点,但我想确保我不会在某处掩盖现有的解决方案。

标签: html css flexbox


【解决方案1】:

使用多个弹性容器会更容易。

但如果你想要一个容器,你仍然可以这样做,有这些假设:

  • 6和7的宽度已知
  • 2、3、4的高度已知

那么,你可以

  • 使用行布局

    ┌─┬─┬─┬─┬─┬─┬─┐
    │1│2│3│4│5│6│7│
    └─┴─┴─┴─┴─┴─┴─┘
    
  • 重新排序弹性项目:1,6,2,3,4,5,7

    ┌─┬─┬─┬─┬─┬─┬─┐
    │1│6│2│3│4│5│7│
    └─┴─┴─┴─┴─┴─┴─┘
    
  • 允许使用flex-wrap: wrap 换行。

  • 使用伪元素在 2 之前和 4 之后强制换行

    ┌─┬─┐
    │1│6│
    ├─┼─┼─┐
    │2│3│4│
    ├─┼─┼─┘
    │5│7│
    └─┴─┘
    
  • 在 6 和 7 上使用 flex-grow: 0。在其他的上使用 flex-grow: 1

    ┌─────────┬─┐
    │    1    │6│
    ├───┬───┬─┴─┤
    │ 2 │ 3 │ 4 │
    ├───┴───┴─┬─┤
    │    5    │7│
    └─────────┴─┘
    
  • 将所需的w 设置为 6 和 7。将 margin-right: w 添加到 4

    ┌─────┬───┐
    │  1  │ 6 │
    ├─┬─┬─┼───┘
    │2│3│4│
    ├─┴─┴─┼───┐
    │  5  │ 7 │
    └─────┴───┘
    
  • 将所需的高度 h 设置为 2、3 和 4。将 margin-bottom: -h/2 添加到 6,将 margin-top: -h/2 添加到 7。

    ┌─────┬───┐
    │  1  │ 6 │
    ├─┬─┬─┤   │
    │2│3│4├───┤
    ├─┴─┴─┤ 7 │
    │  5  │   │
    └─────┴───┘
    
  • 此外,最好将widthmax-width 添加到2、3、4。否则,如果它们的内容足够宽,它们将被放置在不同的行中,从而破坏了布局。

代码如下:

#flex-layout {
  display: flex; /* Magic begins */
  flex-wrap: wrap; /* Multiline */
}
#item1 { order: 1; }
#item6 { order: 2; }
#item2 { order: 3; }
#item3 { order: 4; }
#item4 { order: 5; }
#item5 { order: 6; }
#item7 { order: 7; }
#flex-layout > div {
  border: 1px solid;
  box-sizing: border-box;
}
#item2, #item3, #item4 {
  height: 50px; /* h */
}
#item6 {
  margin-bottom: -25px; /* -h/2 */
}
#item7 {
  margin-top: -25px; /* -h/2 */
}
#item1, #item2, #item3, #item4, #item5 {
  flex-grow: 1;
}
#item6, #item7 {
  width: 25%; /* w */
  flex-grow: 0;
}
#item4 {
  margin-right: 25%; /* w */
}
#flex-layout:before {
  /* Force line break before #item2 */
  content: '';
  width: 100%;
  order: 3;
}
#flex-layout:after {
  /* Force line break after #item4 */
  content: '';
  width: 100%;
  order: 5;
}
<div id="flex-layout">
  <div id="item1">1</div>
  <div id="item2">2</div>
  <div id="item3">3</div>
  <div id="item4">4</div>
  <div id="item5">5</div>
  <div id="item6">6</div>
  <div id="item7">7</div>
</div>

【讨论】:

  • 这行得通,但它看起来像一个 hack,可能不会在所有情况下都有效。似乎应该有更好的方法来做到这一点。
  • @sigilbaram 好吧,灵活的项目可以按列或按行流动。如果你想在不添加更多弹性容器的情况下混合使用这些容器,你必须使用这样的技巧。否则是不可能的。
【解决方案2】:

我的解决方案使用绝对位置。

#flex-layout {
  border: 4px solid tomato;  
  width: 100%;
  display: flex;
  flex-flow: row wrap;
  position: relative;
  min-width: 200px;
}
#flex-layout div {
  box-sizing: border-box;
  border: 4px solid white;
  background: #ddd;
  padding: 1em;
  text-align: center;
  flex: 0 1 25%;
}
#flex-layout #item1 {
  flex: 0 1 75%;
  margin-right: 25%;  
}
#flex-layout #item5 {
  flex: 0 1 75%;
}
#flex-layout #item6 {
  width: 25%; height: 50%;
  position: absolute;  
  top: 0; right: 0;
}
#flex-layout #item7 {
  width: 25%; height: 50%;
  position: absolute;
  top: 50%; right: 0;
}
  <body>
    <div id="flex-layout">
      <div id="item1">1</div>
      <div id="item2">2</div>
      <div id="item3">3</div>
      <div id="item4">4</div>
      <div id="item5">5</div>
      <div id="item6">6</div>
      <div id="item7">7</div>
    </div>

【讨论】:

    【解决方案3】:

    如果现在有人碰巧遇到这种情况,实现这种布局的一种不那么骇人听闻的方法是更新的网格布局系统。网格更适合这种布局,而 flex 更适合在单行/列中分布项目(包括垂直居中元素),或者当项目沿 flex 轴的大小不一致并将它们在多个中相互排列时行/列不是问题。

    #grid-layout {
        display: grid;
        grid-gap: 1em;
        /* 4 columns each 25% width - 3/4 of an em for the grid-gap */
        grid-template-columns: repeat(4, calc(25% - (3em / 4))); 
        grid-template-rows: 10em 4.5em 4.5em 10em;
    }
    
    #grid-layout > div {
        border: solid 1px black;
        padding: .5em;
    }
    
    #item1 { grid-area: 1 / 1 / span 1 / span 3; }
    #item2 { grid-area: 2 / 1 / span 2 / span 1; }
    #item3 { grid-area: 2 / 2 / span 2 / span 1; }
    #item4 { grid-area: 2 / 3 / span 2 / span 1; }
    #item5 { grid-area: 4 / 1 / span 1 / span 3; }
    #item6 { grid-area: 1 / 4 / span 2 / span 1; }
    #item7 { grid-area: 3 / 4 / span 2 / span 1; }
    <div id="grid-layout">
        <div id="item1">1</div>
        <div id="item2">2</div>
        <div id="item3">3</div>
        <div id="item4">4</div>
        <div id="item5">5</div>
        <div id="item6">6</div>
        <div id="item7">7</div>
    </div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-14
      • 2017-11-21
      • 2022-10-15
      • 2020-07-31
      • 2020-03-29
      • 2021-03-12
      • 2013-01-16
      相关资源
      最近更新 更多