根据动态内容计数居中 CSS 网格项目

Posted

技术标签:

【中文标题】根据动态内容计数居中 CSS 网格项目【英文标题】:Centre CSS Grid Items Dependent On Dynamic Content Count 【发布时间】:2022-01-21 07:08:15 【问题描述】:

我有一系列从数据库中获取的图像,当添加三个或更多图像时,它会直观地显示三列。

当图像少于三个时,因为我使用的是display: grid;,所以它当前位于父容器的左侧(在代码示例中,我只是使用红色框来表示图像)。

是否有这样的方法,以便当存在一到两个图像时,这些图像被对齐到父元素的中心。我很感激我可以使用 javascript 来检测存在多少图像,如果它少于三个,添加一个类并将包装器更改为 display: flex,但我想知道这种布局是否可以仅使用 CSS?

由于布局的性质,当存在超过三个图像时,我确实需要使用 CSS Grid。

注意:我已经注释掉了 html 中的两个红色框,以显示只有一个红色框存在时的初始问题。

Codepen:https://codepen.io/anna_paul/pen/xxXrVJQ

body 
  display: flex;
  justify-content: center;
  margin: 0
  width: 100%;
  height: 100vh;


.wrapper 
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 1rem;
  max-width: 1250px;


.box 
  width: 200px;
  height: 200px;
  background: red;
<div class="wrapper">
  <div class="box"></div>
<!--   <div class="box"></div>
  <div class="box"></div> -->
</div>

【问题讨论】:

你能解释一下为什么由于你的布局的性质,它必须是网格而不是弹性盒子吗? ***.com/questions/46276793/… 上的最新回答有帮助吗? @AHaworth 因为图像网格的性质,以及使用网格而不是 flex 进行响应式操作要容易得多。 @paulo_cam 所以当有 1 或 2 张图像时,您需要将它们居中。当有 3 个或更多时,您希望它们左对齐?你能在 OP 中为每个用例显示所需的输出吗?并为容器添加边框,以便我们了解每种情况下的可用空间。 试试这个.wrapper display: grid; grid-template-columns: auto 1fr; grid-template-rows: auto 1fr auto; grid-gap: 1rem; max-width: 1250px; justify-content: center; 【参考方案1】:

如下所示:

.wrapper 
  display: grid;
  grid-auto-flow:column; /* column flow */
  justify-content:center; /* center everything */
  grid-gap: 1rem;
  max-width: 600px;
  border:1px solid;
  margin:10px auto;

/* make sure you only have 3 columns*/
.box:nth-child(3n + 1) grid-column:1
.box:nth-child(3n + 2) grid-column:2
.box:nth-child(3n + 3) grid-column:3
/**/
.box 
  width: 100px;
  height: 100px;
  background: red;
<div class="wrapper">
  <div class="box"></div>
</div>
<div class="wrapper">
  <div class="box"></div>
  <div class="box"></div>
</div>
<div class="wrapper">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
<div class="wrapper">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
<div class="wrapper">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>
<div class="wrapper">
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
</div>

【讨论】:

+1,这是正确的答案,但要小心复制和粘贴,max-width: 600px; 对于 200 像素的正方形不正确。由于我们可以有两个1rem 的差距,您需要设置max-width: calc(600px + 2rem); @BenSouchet 什么副本/过去? 600px 是一个用于演示的随机大值。它无关紧要,可以顺便删除。它与框的宽度无关。【参考方案2】:

因为您对每列使用 1fr,所以即使一列没有内容,它也会占用 33% 的可用空间。您需要指定fr(可用空间的分数)以外的单位:

grid-template-columns: auto auto auto;
grid-template-columns: repeat(3, auto);

grid-template-columns: repeat(3, minmax(min-content, max-content));

使用上述任何一种。在autominmax(min-content, max-content) 之间有一个small difference。

以下是 3 个容器的演示,分别包含 1、2 和 >3 个项目:

body 
  margin: 0;
  width: 100%;
  height: 100vh;


.demo 
  display: flex;
  justify-content: center;


.wrapper 
  display: grid;
  grid-template-columns: repeat(3, minmax(min-content, max-content));
  
  grid-gap: 1rem;
  width: auto;
  max-width: 1250px;


.box 
  width: 200px;
  height: 200px;
  background: red;
  border: 1px solid;
<p>Grid with one item</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
  </div>
</div>
<hr>
<p>Grid with two items</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
    <div class="box">2</div>
  </div>
</div>
<hr>
<p>Grid with >3 items</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
    <div class="box">2</div>
    <div class="box">3</div>
    <div class="box">4</div>
  </div>
</div>

即使列的宽度为 0,1rem grid-gap 也会保留。因此,在您的设置中,flex 中的网格,一个项目网格中的项目将从中心偏离 2rem(2grid-gaps)。如果这不是什么大问题,那就不用担心了。 但如果你想要精确的中心,那么你需要制作grid-gap:0。并使用像margin: 0.5rem;padding:0.5rem 这样的侧网格项目(.box)中的间距来制作人为的网格间隙。

body 
  margin: 0;
  width: 100%;
  height: 100vh;


.demo 
  display: flex;
  justify-content: center;


.wrapper 
  display: grid;
  grid-template-columns: repeat(3, minmax(min-content, max-content));
  
  width: auto;
  max-width: 1250px;


.box 
  width: 200px;
  height: 200px;
  background: red;
  border: 1px solid;
  
  margin: 0.5rem;
<p>Grid with one item</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
  </div>
</div>
<hr>
<p>Grid with two items</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
    <div class="box">2</div>
  </div>
</div>
<hr>
<p>Grid with >3 items</p>
<div class="demo">
  <div class="wrapper">
    <div class="box">1</div>
    <div class="box">2</div>
    <div class="box">3</div>
    <div class="box">4</div>
  </div>
</div>

【讨论】:

感谢 Onkar。在带有两个框的第二个示例中,网格未居中 - 如果您使用开发工具单击它,它会因夹点间隙属性而偏移 1rem。有没有办法防止这种情况发生? 我已经在答案中解释了这一点。添加了第二个代码 sn-p 演示解决方案。【参考方案3】:

使用auto 代替fr 并使用align-content 解决您的问题。

body 
  display: flex;
  justify-content: center;
  margin: 0
  width: 100%;
  height: 100vh;


.wrapper 
  display: grid;
  grid-template-columns: auto auto auto;
  align-content : start;
  /*  grid-gap: 1rem;  */ 
  max-width: 1250px;


.box 
  width: 200px;
  height: 200px;
  background: red;
  margin: 1rem ; 
<div class="wrapper">
  <div class="box"></div>
<!--   <div class="box"></div>
  <div class="box"></div> -->
</div>

【讨论】:

它不会与中心对齐。如果你打开开发者工具,它会向左偏移 2rem,这是由网格间隙属性引起的。 这是真的。你说的对。使用margin 将其准确定位在中心。 我不能使用该解决方案,因为当有两个图像时我需要网格间隙,而当有 3 个或更多图像时,我将获得不需要的额外边距。

以上是关于根据动态内容计数居中 CSS 网格项目的主要内容,如果未能解决你的问题,请参考以下文章

在颤动的网格视图中将最后一行项目居中

居中网格内容,同时左对齐每一行的内容,具有任意项/列宽度

如何在 CSS 网格布局中保持内容居中?

CSS网格区域根据内容推动其他区域不在适当位置

具有最大宽度、居中内容的 CSS 网格布局

用于 Django 中动态内容的 CSS Grid/Flexbox