十年前,我开始学习CSS,目的是修改自己博客的样式。很快,我就能够利用诸如transform之类的更具数学特性、更容易理解的功能来编写炫酷的代码。然而,CSS的其他领域,例如布局,一直是我的痛点。
这篇文章讲述的是我十年前遇到的一个问题,直到最近才找到一个巧妙的解决方案。具体来说,是关于我如何使用现代CSS Grid技术解决一个长期存在的问题,并且在这个过程中,得到了比我最初想象还要酷炫的结果。
需要注意的是,这不是一篇关于如何最佳使用CSS Grid的教程,而更像是我个人学习过程的记录。
问题
我博客上最早发布的内容之一就是城市里的随机照片,所以我萌生了创建一个固定大小缩略图网格的想法。为了美观,我希望这个网格相对于上下的段落垂直居中对齐,但同时,我希望最后一行缩略图相对于网格左对齐。与此同时,文章的宽度(以及其中网格的宽度)将取决于视口。
HTML代码如下所示:
<p></p> <div class="grid--thumbs"> <a href="https://www.php.cn/link/19e321d9f307ccfc1c37106191cbbc74"> <img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174381745622040.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Cool Little CSS Grid Tricks for Your Blog "> </a> </div> <p></p>
看起来很简单,但这却成为我遇到的最棘手的CSS问题之一。
不理想的解决方案
这些是我多年来尝试过或见过别人建议的方法,但都没有真正解决问题。
浮动方案的局限性
浮动方案最终证明是死胡同,因为我无法弄清楚如何使网格以这种方式垂直居中对齐。
.grid--thumbs { overflow: hidden; } .grid--thumbs a { float: left; }
下面的演示展示了浮动方案的尝试。调整嵌入的大小,看看它们在不同视口宽度下的表现。
inline-block 的不足
起初,这似乎是个更好的主意:
.grid--thumbs { text-align: center } .grid--thumbs a { display: inline-block }
但事实并非如此:
最后一行在这种情况下没有左对齐。
在某个时候,由于CodePen上的意外CSS自动完成,我发现了名为text-align-last
的属性,它决定块的最后一行如何对齐。
不幸的是,在网格上设置text-align-last: left
也不是我想要的解决方案:
在这一点上,我实际上考虑放弃垂直居中网格的想法。text-align: justified
和text-align-last: left
的组合能否在网格上产生更好的结果?
结果并非如此。除非最后一行只有一个缩略图,并且列之间的间隙不太大。调整下面的嵌入大小,看看我的意思。
这几乎就是两年前我的处境,经过九年的尝试和失败,我仍然无法找到这个问题的解决方案。
凌乱的Flexbox技巧
一个一开始看起来可行的Flexbox解决方案是在网格上添加一个::after
伪元素,并在缩略图和这个伪元素上设置flex: 1
:
.grid--thumbs { display: flex; flex-wrap: wrap; a, &::after { flex: 1; } img { margin: auto; } &:after { content: 'AFTER'; } }
下面的演示展示了这种方法是如何工作的。我已经为缩略图和::after
伪元素添加了紫色边框,以便更容易看出发生了什么。
这并不是我想要的,因为缩略图网格没有垂直居中对齐。也就是说,只要最后一行比其他行少一个图像,它看起来还不错……一旦发生变化,如果缺少更多项目或没有项目,布局就会中断。
这是一个很糟糕的想法。另一个方法是不使用伪元素,而是在缩略图之后添加与我们期望拥有的列一样多的空div。
我们应该能够近似估计预期列数,因为缩略图的大小是固定的,并且我们可能希望设置文章的最大宽度,因为跨越整个屏幕宽度的文本在视觉上会使眼睛疲劳。将最大宽度除以固定的缩略图宽度应该会给出在这种情况下最大列数。
第一个空元素将占据未完全填充缩略图的行,其余元素将溢出到其他行。但由于它们的高度为零,因此在视觉上无关紧要。
这种方法确实有效,但同样,它很笨拙,并且仍然没有产生我想要的确切结果,因为它有时会在列之间留下大而难看的间隙。
Grid 解决方案?
鉴于其名称,网格布局一直听起来像是答案。问题是,我当时看到的所有示例都使用了预定义的列数,这对于这种特定模式不起作用,在这种模式下,列数由视口宽度确定。
去年,在编写一系列单元素纯CSS背景图案时,我想到生成一堆媒体查询,这些查询将修改一个CSS变量--n
,该变量对应于用于设置grid-template-columns
的列数。
$w: 13em; $h: 19em; $f: $h/$w; $n: 7; $g: 1em; --h: #{$f*$w}; display: grid; grid-template-columns: repeat(var(--n, #{$n}), var(--w, #{$w})); grid-gap: $g; place-content: center; @for $i from 1 to $n { @media (max-width: ($n - $i 1)*$w ($n - $i 2)*$g) { --n: #{$n - $i} } }
当时我对这个想法非常自豪,尽管我现在回想起来觉得很尴尬。每个可能的列数一个媒体查询并不是理想的,更不用说当网格宽度不等于视口宽度但仍然有点灵活并且还取决于其同级元素的宽度时,它也不太好用了。
魔幻般的解决方案
在使用CSS Grid并未能理解为什么repeat()
函数在特定情况下不起作用时,我最终找到了一个更好的解决方案。这太令人沮丧了,促使我去MDN网站查看,我碰巧注意到了auto-fit
关键字,虽然我不理解解释,但我有一种预感它可以帮助解决这个其他问题,所以我放弃了其他所有事情,尝试了一下。
这就是我得到的:
.grid--thumbs { display: grid; justify-content: center; grid-gap: .25em; grid-template-columns: repeat(auto-fit, 8em); }
我还发现了minmax()
函数,它可以代替网格项目上的固定大小。我仍然无法完全理解minmax()
是如何工作的——我玩得越多,就越不理解它——但在这种情况下,它看起来像是创建网格,然后等比例拉伸其列,直到它们填满所有可用空间:
grid-template-columns: repeat(auto-fit, minmax(8em, 1fr));
我们在这里可以做的另一件很酷的事情是防止图像在比网格元素更宽时溢出。我们可以通过将最小8em替换为min(8em, 100%)
来做到这一点。这基本上确保图像永远不会超过100%,但永远不会低于8em。感谢Chris的建议!
请记住,min()
函数在Chromium之前的Edge中不起作用!
请记住,只有当所有图像都具有相同的纵横比(就像我在这里使用的正方形图像一样)时,这才能产生良好的效果。对于我的博客来说,这不是问题,因为所有照片都是用我的索尼爱立信W800i手机拍摄的,它们都具有相同的纵横比。但是,如果我们删除具有不同纵横比的图像,网格看起来就不那么好了:
当然,我们可以将图像高度设置为固定值,但这会扭曲图像……除非我们将object-fit
设置为cover
,这解决了我们的问题!
另一个想法是将第一个缩略图变成一种跨越所有网格列的横幅。唯一的问题是我们不知道列数,因为这取决于视口。但是,有一个解决方案——我们可以将grid-column-end
设置为-1!
.grid--thumbs { /* same styles as before */ a:first-child { grid-column: 1/ -1; img { height: 13em } } }
第一张图片的高度比其他图片都大。
当然,如果我们希望图像跨越除最后一列之外的所有列,我们将将其设置为-2等等……负列索引是可以的!
auto-fill
是我在MDN上注意到的另一个网格属性关键字。这两个关键字的解释都是长篇大论,没有视觉效果,所以我发现它们并没有什么用。更糟糕的是,在上面的任何网格演示中将auto-fit
替换为auto-fill
都不会产生任何区别。即使查看文章或尝试示例后,它们如何真正工作以及它们有何不同仍然是一个谜。
但是,尝试不同的方法并在各种场景中查看结果,最终让我得出结论:如果我们使用minmax()
列宽而不是固定列宽(例如8em),那么最好使用auto-fill
而不是auto-fit
,因为如果我们只有几张图像,结果看起来会更好,如下面的交互式演示所示:
我认为我个人最喜欢的是最初的缩略图网格的想法,它垂直居中对齐并且具有几乎固定的列宽(但仍然使用min(100%, 15em)
而不是仅仅是15em)。归根结底,这是一个个人喜好问题,在下面的演示中可以看到的内容恰好看起来对我来说更好:
我在这里使用auto-fit
,因为它产生的结果与auto-fill
相同,并且字符更少。但是,我在制作这个时没有理解的是,这两个关键字产生相同的结果,因为图库中的项目比我们需要填充一行所需的更多。
但是一旦发生变化,auto-fit
和auto-fill
就会产生不同的结果,如下所示。您可以更改justify-content
值和放置在网格上的项目数量:
我不确定哪个是更好的选择。我想这也取决于个人喜好。结合justify-content: center
,auto-fill
似乎是更合乎逻辑的选择,但同时,auto-fit
会产生更好的视觉效果。
以上是很酷的小CSS网格技巧的详细内容。更多信息请关注PHP中文网其他相关文章!

在这篇文章中,布莱克·莫里(Blackle Mori)向您展示了一些骇客,同时试图推动同位HTML支持的极限。如果您敢于使用这些,以免您也被标记为CSS罪犯。

具有CSS的自定义光标很棒,但是我们可以将JavaScript提升到一个新的水平。使用JavaScript,我们可以在光标状态之间过渡,将动态文本放置在光标中,应用复杂的动画并应用过滤器。

互动CSS动画和元素相互启动的元素在2025年似乎更合理。虽然不需要在CSS中实施乒乓球,但CSS的灵活性和力量的增加,可以怀疑Lee&Aver Lee&Aver Lee有一天将是一场

有关利用CSS背景滤波器属性来样式用户界面的提示和技巧。您将学习如何在多个元素之间进行背景过滤器,并将它们与其他CSS图形效果集成在一起以创建精心设计的设计。

好吧,事实证明,SVG的内置动画功能从未按计划进行弃用。当然,CSS和JavaScript具有承载负载的能力,但是很高兴知道Smil并没有像以前那样死在水中

是的,让#039;跳上文字包装:Safari Technology Preview In Pretty Landing!但是请注意,它与在铬浏览器中的工作方式不同。

此CSS-tricks更新了,重点介绍了年鉴,最近的播客出现,新的CSS计数器指南以及增加了几位新作者,这些新作者贡献了有价值的内容。

在大多数情况下,人们展示了@Apply的@Apply功能,其中包括Tailwind的单个property实用程序之一(会改变单个CSS声明)。当以这种方式展示时,@Apply听起来似乎很有希望。如此明显


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

DVWA
Damn Vulnerable Web App (DVWA) 是一个PHP/MySQL的Web应用程序,非常容易受到攻击。它的主要目标是成为安全专业人员在合法环境中测试自己的技能和工具的辅助工具,帮助Web开发人员更好地理解保护Web应用程序的过程,并帮助教师/学生在课堂环境中教授/学习Web应用程序安全。DVWA的目标是通过简单直接的界面练习一些最常见的Web漏洞,难度各不相同。请注意,该软件中

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器