css 具有完美方形单元格的响应式网格布局

ie3xauqp  于 2023-01-10  发布在  其他
关注(0)|答案(1)|浏览(116)

我有一个<section>元素,它不能大于100vh,也不能宽于100vw。理想情况下,它应该遵循其父容器的尺寸。
<section>应该有一个使用css变量的网格布局; var(--cols, 56)var(--rows, 32)
网格中的每个单元格的比例必须为1:1,这意味着单元格宽度必须始终===单元格高度。
如果viewport(父元素)会增大,除非这会使单元格不是正方形。如果是这种情况,<section>元素应该居中。因此,如果viewport宽度变大而viewport高度变小,<section>将水平居中。但是如果viewport高度变大而viewport宽度变小,<section>元素垂直居中。
这是我目前掌握的情况:

<section #widgets>
  <ng-container *ngFor="let widget of widgetConfig">
    <ng-container [libTileContainer]="widget"></ng-container>
  </ng-container>
</section>
section {
    display: grid;
    gap: 5px;
    grid-template-columns: repeat(
      var(--cols, 56),
      calc(((100vw - (var(--cols, 56) * 5px) - 2rem) / (var(--cols, 56))))
    );
    grid-template-rows: repeat(
      var(--rows, 32), 
      calc(((100vw - (var(--cols, 56) * 5px) - 2rem) / (var(--cols, 56))))
    );
    max-width: 100%;
    max-height: 100%;
  }

这考虑了单元格的垂直度,但它会从父单元格中渗出。计算也只考虑了视口的宽度而不是高度。
我怎样才能达到我想要的?

yr9zkbsy

yr9zkbsy1#

要设置网格项的高度和宽度,您可以使用这样一种策略:根据可用空间内应该容纳的列数和行数来计算高度和宽度,然后在两个属性上使用两者中较小的一个。
https://developer.mozilla.org/en-US/docs/Web/CSS/min
min()CSS函数用于将逗号分隔表达式列表中的最小(最大负值)值设置为CSS属性值。
在这个演示中,我稍微重构了一些选择:

  • 我删除了列数的默认值以简化代码。无论如何,它可以定义为其他自定义属性
  • 我使用函数min来确定候选项的高度和宽度中哪一个较低
  • 默认情况下,我使用place-content使项目居中
  • 我使用grid-auto-rows来确定行的大小,因为在这里指出多少行并不重要
  • 我告诉div取容器的整个宽度和高度
const items = 20;
const cols = 5;
const rows = 4;

initSection(items, cols, rows);

function initSection(items, cols, rows){
  const parent = document.querySelector('section');
  for(i=0;i<items;i++){
    const item = document.createElement('div');
    item.innerText = i+1;
    parent.append(item);  
  }
  parent.dataset.col = cols;
  parent.dataset.col = rows;
}
:root{
  --cols: 56;
  --rows: 32;
}

*{
  box-sizing: border-box;
}

html, body{
  margin: 0;
  overflow: hidden; /*just to make sure the content doesn't overflow the viewport*/
}

section::before{
  /*this to show that the same dynamic strategy here worked instead*/
  --cols: attr(data-cols);
  --rows: attr(data-rows);
  
  position: absolute;    
  content: var(--cols) 'x' var(--rows);
  border: dashed 4px gray;
  padding: 0 .2em;
  font-size: 1.5rem;
  top: .2em;
  left: .4em;
}

section {  
  /*!this didn't work :(*/  
  /*
  --cols: attr(data-cols number, 56);
  --row: attr(data-rows number, 32);
  */
      
  --cols: 5;
  --rows: 4;  
  
  --gap: 5px;
  --col-size: calc(((100vw - (var(--cols) * var(--gap))) / (var(--cols))));  
  --row-size: calc(((100vh - (var(--rows) * var(--gap))) / (var(--rows))));    
  --size: min(var(--col-size), var(--row-size));
  
  display: grid;
  place-content: center;
  gap: var(--gap);
  grid-template-columns: repeat( var(--cols), var(--size));
  /*grid-template-rows: repeat( var(--rows), var(--size));*/
  grid-auto-rows: var(--size);
  width: 100vw;
  height: 100vh;      
}

section{
  border: solid red;
}

section div {  
  border: solid;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: 2rem;
}
<section data-cols="5" data-rows="4">    
  <!-- 
    <div>1</div>
    ...
  -->
</section>

相关问题