根据动态内容计数居中 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));
使用上述任何一种。在auto
和minmax(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 网格项目的主要内容,如果未能解决你的问题,请参考以下文章