如何创建一个跨越2列2行的CSS网格布局盒子?

25

我按照最新的CSS Grid规范创建了一个网格布局,但我对它还不是完全熟悉。我尝试创建以下布局,而不必为每个网格子项定义网格区域。

codepen

body {
  max-width: 1024px;
  margin: 10px auto;
}

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  grid-template-areas: "a a b" "a a c" "d e f";
}

.grid__thing {
  background-color: rebeccapurple;
}

.a {
  grid-area: a;
}

.b {
  grid-area: b;
}

.c {
  grid-area: c;
}

.d {
  grid-area: d;
}

.e {
  grid-area: e;
}

.f {
  grid-area: f;
}

img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="grid">
  <div class="grid__thing a">
    <img src="https://placehold.it/1360x880" alt="" />
  </div>
  <div class="grid__thing b">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing c">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing d">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing e">
    <img src="https://placehold.it/1327x817" alt="" />
  </div>
  <div class="grid__thing f">
    <img src="https://placehold.it/1327x817" alt="" />
  </div>
</div>

理想情况下,我希望能够在网格父元素中设置所有网格尺寸属性,然后仅在网格项目A中定义属性以跨越2列和2行。

目前的做法是为每个网格区域指定一个唯一的类,例如:
.grid {
    display: grid;
    grid-gap: 10px;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows:  1fr 1fr 1fr;
    grid-template-areas: "a a b"
                         "a a c"
                         "d e f";
.a {
    grid-area: a;
}
.b {
    grid-area: b;
}
.c {
    grid-area: c;
}
.d {
    grid-area: d;
}
.e {
    grid-area: e;
}
.f {
    grid-area: f;
}

想要像这样做,这样我就不必为每个网格项创建一个唯一的CSS类:

.grid {
    display: grid;
    grid-gap: 10px;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows:  1fr 1fr 1fr;
    grid-template-areas: "a a b"
                         "a a c"
                         "d e f";
}
.a {
    // The only unique selector, so this is the only thing that
    // should be given unique styling
}
3个回答

49

如果您不想为每个网格项定义网格区域,请不要使用需要为每个网格项定义名称的grid-template-areas属性。

相反,只需在容器上使用grid-template-columnsgrid-template-rows即可。

然后,使用grid-columngrid-row将2x2大小应用于第一个网格项。

grid-container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 100px);
  grid-gap: 10px;
}

grid_item:first-child {
  grid-column: 1 / 3; /* span from grid column line 1 to 3 (i.e., span 2 columns) */
  grid-row: 1 / 3;    /* same concept, but for rows */
}

/* non-essential decorative styles */
grid_item {
  background-color: aqua;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 1.5em;
}
<grid-container>
  <grid_item>A</grid_item>
  <grid_item>B</grid_item>
  <grid_item>C</grid_item>
  <grid_item>D</grid_item>
  <grid_item>E</grid_item>
  <grid_item>F</grid_item>
</grid-container>

codepen演示


1
好的回答,但我对问题的理解略有不同。也许我错了,不过。 - vals

11

与 Michael Benjamin 的答案不同,这里不再告诉你的元素应该在哪一列 / 行开始 / 结束

grid-column: 1 / 3;

您还可以告诉元素它应该跨越多少行/列 span

grid-column: span 2;
/*same rule as*/
grid-column-start: span 2;
grid-column-end: auto;

使用这种方式,元素将被放置在文档流中,并跨越多个列/行。

你仍然可以结合这个规则和起点,例如:

grid-column: 1 / span 2;
/*same rule as*/
grid-column-start: 1;
grid-column-end: span 2;

当然可以通过交换 `column` 和 `row`,使元素横跨多行。
grid-row: span 2;

对于大多数人来说,这是正确的(可扩展的)答案。 - undefined

3

只需按计划操作,删除无用的类。

body {
  max-width: 1024px;
  margin: 10px auto;
}

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  grid-template-areas: "a a" "a a";
}

.grid__thing {
  background-color: rebeccapurple;
}

.a {
  grid-area: a;
}

img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="grid">
  <div class="grid__thing a">
    <img src="https://placehold.it/1360x880" alt="" />
  </div>
  <div class="grid__thing">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing">
    <img src="https://placehold.it/660x405" alt="" />
  </div>
  <div class="grid__thing">
    <img src="https://placehold.it/1327x817" alt="" />
  </div>
  <div class="grid__thing">
    <img src="https://placehold.it/1327x817" alt="" />
  </div>
</div>


那么你只是使用 grid-template-areas 来调整元素 .a 的大小和位置。其他元素是根据自动放置算法进行对齐,而不是 grid-template-areas。如果您决定重新组织布局并使用 grid-template-areas,则除 .a 外的所有元素都将被忽略。 - Michael Benjamin
上面的答案是可行的,如果你不想重新组织你的布局,但它似乎有点低效,因为字母 b-f 是无用的、毫无意义和任意的。你可以用任何东西替换那些字母,而布局中什么也不会改变。 - Michael Benjamin
1
@Michael_B 是的,你说得对。我已经修复了它。事实是我并不真正相信这就是 OP 所问的...只是为了确定而发帖。 - vals

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