如何使CSS Grid项占用剩余空间?

73
我有一个使用CSS Grid布局构建的卡片。左侧可能有一张图片,右上方可能有一些文本,右下方可能有一个按钮或链接。
在下面的代码中,我如何使绿色区域尽可能地占据空间,同时使蓝色区域尽可能少地占用空间?
绿色应该将蓝色区域向下推。

https://jsfiddle.net/9nxpvs5m/

.grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-areas:
    "one two"
    "one three"
}

.one {
  background: red;
  grid-area: one;
  padding: 50px 0;
}

.two {
  background: green;
  grid-area: two;
}

.three {
  background: blue;
  grid-area: three;
}
<div class="grid">
  <div class="one">
    One
  </div>
  <div class="two">
    Two
  </div>
  <div class="three">
    Three
  </div>
</div>


虽然不是对问题的直接回答,但仍有价值:我会使用flexbox和一个额外的容器来包裹.two.three:https://jsfiddle.net/9nxpvs5m/2/ - domsson
实际问题似乎与标题不符。标题建议尝试占用剩余空间,但实际问题谈论尽可能多或尽可能少地占用空间。 - Michael
6个回答

87

在你的.grid中添加grid-template-rows: 1fr min-content;将会得到你想要的效果 :)

.grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-rows: 1fr min-content;
  grid-template-areas:
    "one two"
    "one three"
}

.one {
  background: red;
  grid-area: one;
  padding: 50px 0;
}

.two {
  background: green;
  grid-area: two;
}

.three {
  background: blue;
  grid-area: three;
}
<div class="grid">
  <div class="one">
    One
  </div>
  <div class="two">
    Two
  </div>
  <div class="three">
    Three
  </div>
</div>

Jens的编辑:为了更好的浏览器支持,可以改用以下方式:grid-template-rows: 1fr auto;,至少在这种情况下是可以的。


1
我曾经遇到过一个类似的问题,那是一个单列四行的网格。使用了 grid-template-rows: auto auto auto 1fr;,现在它会扩展最后一行以填充页面的剩余部分。这正是我的目标——感谢您的提示。 - scottperezfox

2

网格是一系列相交的行和列。

您希望第二列中的两个项目根据其内容高度自动调整其行高。

这不是网格的工作方式。对第二列行高度的更改也会影响第一列。

如果您必须使用CSS Grid,则我会为容器设置12行,然后根据需要跨越行。

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

.one {
  grid-row: 1 / -1;
  background: red;
}

.two {
  grid-row: span 10;
  background: lightgreen;
}

.three {
  grid-row: span 2;
  background: aqua;
}

.grid > div {
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="grid">
  <div class="one">One</div>
  <div class="two">Two</div>
  <div class="three">Three</div>
</div>

否则,您可以尝试使用flexbox解决方案。

.grid {
  display: flex;
  flex-flow: column wrap;
  height: 200px;
}

.one {
  flex: 0 0 100%;
  width: 30%;
  background: red;
}

.two {
  flex: 1 0 1px;
  width: 70%;
  background: lightgreen;
}

.three {
  background: aqua;
}

.grid>div {
  display: flex;
  align-items: center;
  justify-content: center;
}
<div class="grid">
  <div class="one">One</div>
  <div class="two">Two</div>
  <div class="three">Three</div>
</div>


我曾考虑过使用min-content的方法,但是这个值在浏览器上的支持较弱。当我测试时,在Safari和Firefox中它并没有起作用。 - Michael Benjamin

1
当使用网格布局时,如果您使用了网格模板区域,并且偶然给某个区域指定了宽度,则会自动留下空间。在这种情况下,将网格模板列设置为 min-content 或 max-content,以便它可以自动调整位置。

1

一种可能的方法是将twothree分组在一起,并使用flexbox

.grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-areas: "one two"
}

.one {
  background: red;
  grid-area: one;
  padding: 50px 0;
}

.wrap {
  grid-area: two;
  display: flex;
  flex-direction: column;
}

.two {
  background: green;
  flex: 1;
}

.three {
  background: blue;
}
<div class="grid">
  <div class="one">
    One
  </div>
  <div class="wrap">

    <div class="two">
      Two
    </div>
    <div class="three">
      Three
    </div>
  </div>
</div>


完全符合我的想法。Flexbox 真的是我现在首选的解决方案。然而,遗憾的是 flexbox 实际上不够 flexible,无法在没有额外容器包裹 .two.three 的情况下实现这种简单的布局 - 或者有其他方法吗? - domsson
@domsson 我想不出来有什么问题 :) - sol
1
我认为这是一个解决方法,所以在接受它作为答案之前我会等一段时间。如果存在网格解决方案,它将被接受为答案。 - Jens Törnell

0

这绝对不是最优雅的解决方案,可能也不是最佳实践,但你总可以添加更多的代码行。

"one two"

在你有的那部分之前

"one three"

所以最终看起来像这样

.grid {
  display: grid;
  grid-template-columns: 1fr 3fr;
  grid-template-areas:
    "one two"
    "one two"
    "one two"
    "one three"
}

再说一遍,我很确定这只是一个解决方法,还有更好的解决方案...但公平地说,这确实有效。


-5

只需在要填充网格的项目的CSS类中使用width: 100%height: 100%。如果您不希望网格容器内的网格项增长超过某个大小,请加入max-width属性和max-height属性。


等等,为什么评分如此负面?!这实际上是一个有效的解决方案。点赞! - undefined
1
也许这不被视为一个好的做法?我不知道多年过去了,现在我从事后端工作,所以我把这个交给前端专家们处理。 - undefined

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