CSS 网格 children 设置的纵横比适合 parent

CSS Grid with children with set aspect ratio fit to parent

我需要一个列数和行数固定的网格。每一列和每一行都被完全填满。每个单元格由两部分组成 - 具有固定纵横比的图像(所有单元格都相同)和具有固定高度的标题。我需要网格以适应 parent(类似于 background-size: contain 的工作方式)。到目前为止,我想出了解决方案,它只适合网格以匹配 parent.

的宽度

注意:在这个例子中 parent 的网格是整个屏幕,在实际情况下它可以是独立于屏幕大小的任何大小(所以我们不能使用 vwvh 单位).

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(2, 1fr);
  padding: 15px;
  gap: 15px;
}
.grid-child {
  background-color: red;
}
.fixed-ratio {
  aspect-ratio: 4/3;
  background-color: orange;
}
.caption {
  background-color: yellow;
}
<div class="grid">
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">1</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">2</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">3</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">4</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">5</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">6</div></div>
</div>

除非我完全误解了您想要实现的目标,只需将 height 100% 添加到 .grid 即可使网格填满屏幕。

调整屏幕将允许单元格(图像)的内容缩放到父级的宽度,同时保持纵横比。

注意

网格子图像无法填充单元格的高度,同时保持 4/3 的纵横比,除非 container/screen 的宽度也是 4/3 的纵横比。

网格子文本无法填充单元格,因为它具有固定的高度。

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
}
.grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(2, 1fr);  
  gap: 15px;
  height:100%;
}
.grid-child {
  background-color: red;
}
.fixed-ratio {
  aspect-ratio: 4/3;
  background-color: orange;
}
.caption {
  background-color: yellow;
}
<div class="grid">
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">1</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">2</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">3</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">4</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">5</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">6</div></div>
</div>

我设法使用一些 Javascript 和 CSS calc 函数的丑陋用法找到了一个解决方案。我欢迎提供相同结果但不使用 JS 的其他解决方案。您可以使用此代码段来比较您自己的结果(请全屏打开代码段并调整大小 window 以查看实际效果)。

document.addEventListener('DOMContentLoaded', () => {
  new ResizeObserver(entries => {
    for (let entry of entries) {
      entry.target.style.setProperty('--parent-width', entry.contentRect.width + 'px');
      entry.target.style.setProperty('--parent-height', entry.contentRect.height + 'px');
    }
  }).observe(document.body);
});
  * {
    box-sizing: border-box;
  }
  html {
    --columns: 3;
    --rows: 2;
    --ratio: 4 / 3;
    --gap: 15px;
    --caption-height: 20px;
  }
  html, body {
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
  }
  .grid {
    background-color: red;
    padding: calc(var(--gap) / 2);
    width: calc(
      min(
        var(--parent-width),
        (((var(--parent-height) - var(--gap)) / var(--rows) - var(--caption-height) - var(--gap)) * (var(--ratio)) + var(--gap)) * var(--columns) + var(--gap)
      )
    );
    height: calc(
      min(
        var(--parent-height),
        (((var(--parent-width) - var(--gap)) / var(--columns) - var(--gap)) / (var(--ratio)) + var(--caption-height) + var(--gap)) * var(--rows) + var(--gap)
      )
    );
    margin: auto;
  }
  .grid-child {
    padding: calc(var(--gap) / 2);
    width: calc(100% / var(--columns));
    height: calc(100% / var(--rows));
    float: left;
  }
  .fixed-ratio {
    background-color: orange;
    height: calc(100% - var(--caption-height));
  }
  .caption {
    background-color: yellow;
    height: var(--caption-height);
}
<div class="grid">
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">1</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">2</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">3</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">4</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">5</div></div>
  <div class="grid-child"><div class="fixed-ratio"></div><div class="caption">6</div></div>
</div>