CSS网格布局中,每行可以有不同数量的列吗?

43

.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: 100px;
  grid-auto-rows: 60px;
  grid-gap: 15px;
}

.col {
  background-color: tomato;
}
<div class="grid">
  <div class="col"></div>
  <div class="col"></div>
  <div class="col"></div>
  <div class="col"></div>
  <div class="col"></div>
</div>

这将创建2行,第一行高度为100像素,第二行自动创建,高度为60px。第二行中的2列宽度为1fr

通过CSS Grid/Flexbox是否可以水平居中第二行中的2列?即每行包含不同数量的列。

我试图解决浏览器中使用CSS Grid框架的一个微不足道的用例,如果您使用Flexbox构建网格,则非常容易实现。

但我能否使用CSS Grid实现呢?

这里是我尝试实现的CodePen演示


一个网格,根据定义,每行必须有相同数量的列。你需要使用flexbox而不是grid。 - jhpratt
类似这样的东西可能会很有用:https://dev59.com/q6Hia4cB1Zd3GeqPX7mu - instead
6个回答

47

您的问题是:

在CSS Grid中,我可以每行有不同数量的列吗?

但接着你又说了这个:

通过CSS Grid / Flexbox,是否可以使第二行中的2列水平居中?

看起来你陷入了一个经典的XY问题:你关注的是你的尝试解决的问题而不是你的实际问题

是的,可以使用CSS Grid将列(和网格项和内容)居中。 (在此处查看各种方法:Centering in CSS Grid

否则,在CSS Grid或任何网格中,每行具有不同数量的列是不可能的。否则,你就没有网格了。

由于外观通常是布局中最重要的,因此您可以使用CSS Grid构建在第一行中具有三个“列”和在第二行中具有两个“列”的外观 - 居中。

在下面的示例中,我将网格容器中的水平空间分成12列。然后,我使用Grid的基于线条的定位功能来定位和调整项目的大小。

.grid {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  grid-auto-rows: 40px;
  grid-gap: 10px;
}

.col:nth-child(-1n + 3) {
  grid-column: span 4;
}
.col:nth-last-child(2) {
  grid-row-start: 2;
  grid-column: 3 / span 4;
}
.col:nth-last-child(1) {
  grid-row-start: 2;
  grid-column: 7 / span 4;
}
.col {
  background-color: tomato;
}
<div class="grid">
  <div class="col"></div>
  <div class="col"></div>
  <div class="col"></div>
  <div class="col"></div>
  <div class="col"></div>
</div>

CodePen演示

这是使用Firefox DevTools时的样子:

enter image description here


1
当与媒体查询结合使用时,这是一个非常灵活的解决方案。 - Optimae
这是一种通用的方法,可以保持这个无限的(未知数量的行将显示为3、2、3、2...)。 - Mosh Feu
1
@MoshFeu,您可以通过针对每个需要重复的五个项目来设置模式。https://codepen.io/mbb7774/pen/eYpVgQg?editors=1100 - Michael Benjamin

15
如果你的行有不同数量的单元格,并且这些单元格没有全部布置在一个二维(行和列)空间中,那么你没有一个网格。按定义,网格包含固定数量的行和列,以及跨越其中一个或多个的单元格。也许你会有多个不同的网格,每行一个,但这实际上是违背了网格的整个目的。

如果你的行数变化是对称的或者遵循某种模式,你可以按照Michael_B的建议基于公共分母构建网格,并以马赛克样式填充网格区域。这与目前flexbox解决方案一样复杂,但是一旦更多的浏览器实现了flexbox fragmentation,flexbox应该成为优于网格的明显选择。


哦,那真是个糟糕的事情,是啊,在这个框架内我的问题甚至都没有意义。谢谢。 - knitevision
@knitevision 或许可以顺带一提,你可以将 grid-template-rows 设置为 auto,以在列中布置不同数量的盒子。但是你无法像示例中那样居中第二行的盒子。CSS 网格相当“严格”。 - stewo
“网格”是刚性的。为什么人们似乎认为这些限制只适用于CSS网格?事实上,CSS网格比传统网格更加灵活。 - BoltClock

8
您可以尝试这种方式:

.container {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: [col] 100px [col] 100px [col] 100px [col] 100px;
  grid-template-rows: [row] auto [row] auto [row];
  background-color: #fff;
  color: #444;
}

.col {
  background-color: #444;
  color: #fff;
  border-radius: 5px;
  padding: 20px;
  font-size: 150%;
}

.a {
  grid-column: col / span 2;
  grid-row: row;
}

.b {
  grid-column: col 3 / span 2;
  grid-row: row;
}

.c {
  grid-column: col;
  grid-row: row 2;
}

.d {
  grid-column: col 2 / span 3;
  grid-row: row 2;
}

.e {
  grid-column: col / span 4;
  grid-row: row 3;
}
<div class="container">
  <div class="col a">A</div>
  <div class="col b">B</div>
  <div class="col c">C</div>
  <div class="col d">D</div>
  <div class="col e">E</div>
</div>

CodePen: https://codepen.io/anon/pen/MOLrvq


2
你可以使用嵌套网格来解决这个问题。 网格1(覆盖整个区域) 网格2(覆盖第一行) 网格3(覆盖第二行)
通过这种设置,您可以缩短第二行的宽度。

0
如果有人遇到同样的问题,这就是我找出解决方法的方式。我在容器中放置了两个 div,并希望它们具有不同的列。所以我只为每个 div 创建了一个网格。然后我创建了一个1fr行,以及我想要的列数。这个方法非常顺利地解决了我的问题。

你应该添加一段代码片段到你的回答中,以展示你所描述的内容。 - isherwood

0
我通过在子元素中使用网格来实现这一点。

.container {
    display: grid;
    grid-template-columns: 1fr 2fr;
    gap: 5px;
  }
  
  .item {
    background-color: aqua;
    height: 120px;
  }
  
  .item5 {
    display: grid;
    grid-column: 1 / span 2;
    grid-template-columns: 1fr 1fr; /* Divide item5 into 2 equally sized columns */
  }
  
  .item5 > div {
    background-color: aqua;
    height: 310px;
    margin-right: 5px; /* Add margin for gap effect */
  }
   .item5 > div:last-child {
    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="grid.css">
    <title>Grid</title>
</head>
<body>
    <div class="container">
        <div class="item item1"><h1>hello World</h1></div>
        <div class="item item2"><h1>hello World</h1></div>
        <div class="item item3"><h1>hello World</h1></div>
        <div class="item item4"><h1>hello World</h1></div>
        <div class="item5">
            <div>
                <h1>hello World 5</h1>
            </div>
            <div>
                <h1>hello World 5.5</h1>
            </div>
        </div>
        <div class="item item6"><h1>hello World</h1></div>
        <div class="item item7"><h1>hello World</h1></div>
        <div class="item item8"><h1>hello World</h1></div>
        <div class="item item9"><h1>hello World</h1></div>
        <div class="item item10"><h1>hello World</h1></div>
    </div>
</body>
</html>


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