使网格项目消耗另一个已删除项目的 space

Make grid item consume the space of another item that has been removed

基本上我需要做的是设置一个网格,但如果缺少一个元素,另一个元素会延伸以填充 space。

这是我当前所在位置的 Pen 示例:

https://codepen.io/Rockster160/pen/JMLaXY

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

div {
  box-sizing: border-box;
}

.grid {
  height: 100%;
  width: 100%;
  background: white;
  border: 2px solid red;
  display: grid;
  grid-template-columns: 250px auto;
  grid-template-rows: 100px auto 50px;
  grid-template-areas: "sidebar header" 
                       "sidebar content"
                       "sidebar footer";
}

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

.header {
  grid-area: header;
  background: lightblue;
}

.content {
  grid-area: content;
  background: blue;
  border: 5px solid black;
}

.footer {
  grid-area: footer;
  background: orange;
}
<div class="grid">
  <div class="sidebar"></div>
  <div class="header"></div>
  <div class="content"></div>
  <!--   <div class="footer"></div> -->
</div>

footer 是一个可选元素,所以当它不存在时(如代码中注释掉),那么 content 应该伸展并与 sidebar 的底部对齐.

我尝试了使用 min/max 内容和不同 auto 展示位置的各种不同组合,但没有成功。我想如果我有多个名为 content 的元素,它也可以工作,但也没有运气。

非常感谢任何帮助!

最简单的方法是使用 :last-child 选择器:

.content:last-child {
  grid-row: content / footer;
}

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

div {
  box-sizing: border-box;
}

.grid {
  height: 100%;
  width: 100%;
  background: white;
  border: 2px solid red;
  display: grid;
  grid-template-columns: 250px auto;
  grid-template-rows: 100px auto 50px;
  grid-template-areas: "sidebar header" "sidebar content" "sidebar footer";
  margin-bottom: 2rem;
}

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

.header {
  grid-area: header;
  background: lightblue;
}

.content {
  grid-area: content;
  background: blue;
  border: 5px solid black;
}

.content:last-child {
  grid-row: content / footer;
}

.footer {
  grid-area: footer;
  background: orange;
}
<div class="grid">
  <div class="sidebar"></div>
  <div class="header"></div>
  <div class="content"></div>
  <!-- <div class="footer"></div> -->
</div>

<div class="grid">
  <div class="sidebar"></div>
  <div class="header"></div>
  <div class="content"></div>
  <div class="footer"></div>
</div>

或者,我们可以颠倒 HTML 中 .content.footer 元素的顺序(如下所示)并使用 CSS 否定运算符( :not()) 来确定 .content 元素应该占用额外的 space 如果它前面没有 .footer 元素:

:not(.footer) + .content {
  grid-row: content/footer;
}

设置 .content 元素的样式,该元素前面没有紧跟 .footer 兄弟元素,因此它从 content 标识的 grid-row 开始并结束在由 footer 标识的 grid-row 中:

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

div {
  box-sizing: border-box;
}

.grid {
  height: 100%;
  width: 100%;
  background: white;
  border: 2px solid red;
  display: grid;
  grid-template-columns: 250px auto;
  grid-template-rows: 100px auto 50px;
  grid-template-areas: "sidebar header" "sidebar content" "sidebar footer";
}

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

.header {
  grid-area: header;
  background: lightblue;
}

.content {
  grid-area: content;
  background: blue;
  border: 5px solid black;
}

:not(.footer)+.content {
  grid-row: content/footer;
}

.footer {
  grid-area: footer;
  background: orange;
}
<div class="grid">
  <div class="sidebar"></div>
  <div class="header"></div>
  <div class="content"></div>
  <!-- <div class="footer"></div> -->
</div>

<div class="grid">
  <div class="sidebar"></div>
  <div class="header"></div>
  <div class="content"></div>
  <div class="footer"></div>
</div>

参考文献:

将您的 .grid class 更改为

  .grid {
    display: grid;
    grid-template-columns: 250px auto;
    grid-template-rows: 100px auto 50px;
    grid-template-areas:
      "sidebar header"
      "sidebar content"
      "sidebar content";
  }

当您像在笔中一样评论页脚标签时,网格仍在等待那里有一个页脚元素,所以它有点 "saving space" 这个元素

有时使用 flexbox 会更简单。

由于您的容器具有定义的高度(视口),您可以使用 flex-flow: column wrap 创建两列。

然后在内容项上使用 flex: 1,告诉它免费使用 space。

当页脚存在时,内容为其创建 space。当页脚不存在时,内容会消耗所有 space.

.grid {
  display: flex;
  flex-flow: column wrap;
  height: 100vh;
  background: white;
  border: 2px solid red;
}

.sidebar {
  flex: 0 0 100%;
  width: 250px;
  background: green;
}

.header {
  flex: 0 0 100px;
  width: calc(100% - 250px);
  background: lightblue;
}

.content {
  flex: 1;
  width: calc(100% - 250px);
  border: 5px solid black;
  background: blue;
}

.footer {
  flex: 0 0 50px;
  width: calc(100% - 250px);
  background: orange;
}

body { margin: 0; }
div  { box-sizing: border-box; }
<!-- WITH FOOTER -->
<div class="grid">
  <div class="sidebar"></div>
  <div class="header"></div>
  <div class="content"></div>
  <div class="footer"></div>
</div>

<hr>

<!-- WITHOUT FOOTER -->
<div class="grid">
  <div class="sidebar"></div>
  <div class="header"></div>
  <div class="content"></div>
</div>

您在网格样式中强制第 3 行为 50px。

更改它以适应内容,并将 50px 设置为页脚本身的高度:

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

div {
  box-sizing: border-box;
}

.grid {
  height: 100%;
  width: 100%;
  background: white;
  border: 2px solid red;
  display: grid;
  grid-template-columns: 250px auto;
  grid-template-rows: 100px auto max-content;   /* changed last 50px to max-content*/
  grid-template-areas: "sidebar header" 
                       "sidebar content"
                       "sidebar footer";
}

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

.header {
  grid-area: header;
  background: lightblue;
}

.content {
  grid-area: content;
  background: blue;
  border: 5px solid black;
}

.footer {
  grid-area: footer;
  background: orange;
  height: 50px;   /* added */
}
<div class="grid">
  <div class="sidebar"></div>
  <div class="header"></div>
  <div class="content"></div>
  <!--   <div class="footer"></div> -->
</div>

还有另一种可能性,感谢 Michael_B。 grid-template-rows 的语法更清晰:

html,
body {
  height: 100%;
  margin: 0;
  padding: 0;
}

div {
  box-sizing: border-box;
}

.grid {
  height: 100%;
  width: 100%;
  background: white;
  border: 2px solid red;
  display: grid;
  grid-template-columns: 250px auto;
  grid-template-rows: 100px 1fr auto;   
  grid-template-areas: "sidebar header" 
                       "sidebar content"
                       "sidebar footer";
}

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

.header {
  grid-area: header;
  background: lightblue;
}

.content {
  grid-area: content;
  background: blue;
  border: 5px solid black;
}

.footer {
  grid-area: footer;
  background: orange;
  height: 50px;   /* added */
}
<div class="grid">
  <div class="sidebar"></div>
  <div class="header"></div>
  <div class="content"></div>
  <div class="footer"></div>
</div>