如何在网格中使一个div跨越多行和多列?

17

承接之前的问题,我正在尝试将更大的块添加到我的网格布局中。在上一个问题中,我需要将一个div跨越多行。现在的问题是,我需要一个div跨越多行和列。

如果我有一个五个元素的行,如何将更大的元素放在其中央?(因为float会自然地放在一侧)。

以下是一个示例片段:

#wrapper{
  width: 516px;
}
.block{
  display: inline-block;
  width: 90px;
  height: 50px;
  margin: 5px;
  background-color: red;
}
.bigger{
  height: 110px;
}
.larger{
  height: 110px;
  width: 190px;
}
<div id="wrapper">
  <div class="block"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block larger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

我不想在容器元素使用 display: grid,因为Can I Use 显示这是一种目前处于边缘的技术。我希望有一种无需使用网格布局无需使用表格的解决方案。

以下是我希望从上面的代码段中得到的效果:期望效果


3
HTML可以被修改吗? - Michael Benjamin
如果您的HTML无法更改,我建议使用像Isotope这样的库 - 不确定是否有纯CSS解决方案可以真正实现您想要的效果。 - maxinacube
@Michael_B 我正在开发一个“2块包装器”,但希望有另一种方法来完成它。 - PaulCo
3个回答

28
我知道你正在寻求一种不涉及HTML表格或CSS网格布局的答案。你提到你不想使用网格布局,因为浏览器支持较弱。
然而,在你发布问题的同时,大多数主要浏览器发布了新版本,提供了完整的网格布局支持(详见下文)。

CSS Grid使您的布局变得简单。无需更改HTML,添加嵌套容器或在容器上设置固定高度(请参见本页面上我的flexbox答案)。

#wrapper {
  display: grid;                            /* 1 */
  grid-template-columns: repeat(5, 90px);   /* 2 */
  grid-auto-rows: 50px;                     /* 3 */
  grid-gap: 10px;                           /* 4 */
  width: 516px;
}

.tall {
  grid-row: 1 / 3;                          /* 5 */
  grid-column: 2 / 3;                       /* 5 */
}

.wide {
  grid-row: 2 / 4;                          /* 6 */
  grid-column: 3 / 5;                       /* 6 */
}

.block {
  background-color: red;
}
<div id="wrapper">
  <div class="block"></div>
  <div class="block tall"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block wide"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

jsFiddle

它的工作原理:

  1. 建立一个块级网格容器。
  2. grid-template-columns属性设置明确定义的列的宽度。在这种情况下,指示网格创建一个90像素宽的列,并重复5次此过程。
  3. grid-auto-rows属性设置自动生成(隐式)行的高度。在这里,每行的高度为50像素。
  4. grid-gap属性是grid-column-gapgrid-row-gap的速记方式。此规则在网格项之间设置10像素的间隔(不适用于项目和容器之间的区域)
  5. 指示.tall项目跨越第1至第3行和第2至第3列的行线。*
  6. 指示.wide项目跨越第2至第4行和第3至第5列的列线。*
在一个五列网格中有六个列线。在一个三行网格中有四个行线。

CSS Grid的浏览器支持

  • Chrome - 从2017年3月8日(版本57)开始提供完全支持
  • Firefox - 从2017年3月6日(版本52)开始提供完全支持
  • Safari - 从2017年3月26日(版本10.1)开始提供完全支持
  • Edge - 从2017年10月16日(版本16)开始提供完全支持
  • IE11 - 不支持当前规范;仅支持过时版本

这是完整的情况:http://caniuse.com/#search=grid


太好了!你知道我怎么能让一个任意的框在不了解它的同级元素的情况下增大吗? - SB2055
@SB2055,你能提供更多细节吗?也许可以提供一个演示来参考一下?或者考虑发布一个包含完整细节的新问题。 - Michael Benjamin

5
保留您的HTML不变,使用flexbox无法原生地实现该布局。这主要是因为第三列和第四列占据了2 x 2的方框。您可以接近实现此布局:

#wrapper{
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  align-content: flex-start;
  height: 180px;
  width: 516px;
}
.block {
  width: 90px;
  flex: 0 0 50px;
  margin: 5px;
  background-color: red;
}
.bigger{
  flex-basis: 110px;
}
<div id="wrapper">
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>

正如你所看到的,大盒子被分成了几列。

如你在其他参考文章中提到的,由于子元素 (.block) 具有固定高度,我们可以确定容器 (.wrapper) 的高度。

通过知道容器的高度,上面的布局可以使用 flex-direction: columnflex-wrap: wrap 实现。

容器的固定高度作为断点,告诉 flex 项目何时换行。

或者,如果您可以添加容器,则布局变得简单。只需创建四个嵌套的 flex 容器来容纳 1、2、3-4 和 5 列,就完成了。

#wrapper {
  display: flex;
  width: 516px;
}

section {
  display: flex;
  flex-direction: column;
}

.block {
  width: 90px;
  height: 50px;
  margin: 5px;
  background-color: red;
}

.bigger {
  flex-basis: 110px;
}

section:nth-child(3) {
  flex-direction: row;
  flex-wrap: wrap;
  flex: 0 0 200px;
}

section:nth-child(3)>.block:last-child {
  flex: 0 0 190px;
  height: 110px;
}
<div id="wrapper">
  <section>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </section>
  <section>
    <div class="block bigger"></div>
    <div class="block"></div>
  </section>
  <section>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </section>
  <section>
    <div class="block"></div>
    <div class="block"></div>
    <div class="block"></div>
  </section>
</div>

否则,阅读此帖子以获取更多详细信息和其他选项:


1
使用 flexbox 和 flex-direction: row 进行布局。

#wrapper{
  width: 516px;
  display: flex;         /* added */
  flex-flow: row wrap;   /* added */
}
.block{
  display: inline-block;
  width: 90px;
  height: 50px;
  margin: 5px;
  background-color: red;
}
.block:last-child {
  margin-left: 205px;    /* added */
}
.bigger{
  height: 110px;
  margin-bottom: -55px;  /* added */
}
.larger{
  height: 110px;
  width: 190px;
  margin-left: 105px;    /* added */
  margin-bottom: -55px;  /* added */
}
<div id="wrapper">
  <div class="block"></div>
  <div class="block bigger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block larger"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
  <div class="block"></div>
</div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接