本文翻译自 CSS Grid and Custom Shapes, Part 1,略有删改
在失常的开发中,咱们会遇到很多元素块排列对齐的需要,如九宫格抽奖,多张图片上传后等分布局预览,微信朋友圈多张图片展现等。这都是失常的正方形很规整的布局。
如下所示,如果图像不是齐全正方形,而是形态像六边形或菱形怎么办?咱们怎么做呢。事实上,咱们将联合咱们曾经钻研过的 CSS 网格技术,并退出一些 CSS clip-path
和mask
魔法,为您能够设想的任何形态创立精美的图像网格!
雷同的HTML
咱们将要钻研的大多数布局乍一看仿佛很容易实现,但具备挑战性的局部是应用雷同的 HTML 标记来实现它们。咱们能够应用很多包装器、divs 等等,但这篇文章的指标是应用雷同且起码的 HTML 代码,并且依然能够实现咱们想要的所有不同格调的网格。
这就是说,让咱们从以下的HTML开始:
<div class="gallery"> <img src="..." alt="..."> <img src="..." alt="..."> <img src="..." alt="..."> <img src="..." alt="..."> <!-- as many times as we want --></div>
一个带有图像的容器就是咱们在这里所须要的。足已!
六边形 CSS 网格
这个形态有时也称为蜂窝网格。
首先,咱们应用clip-path
在图像上应用来创立六边形形态,并将它们全副放在同一个网格区域中,以便它们重叠。
.gallery { --s: 150px; /* controls the size */ display: grid;}.gallery > img { grid-area: 1/1; width: var(--s); aspect-ratio: 1.15; object-fit: cover; clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0 50%);}

此时所有的图像都是六边形并且重叠在一起。所以看起来咱们只有一个六边形的图像元素,但实际上有七个。下一步将把图像平移到它们正确搁置的网格上。
保留其中一张图像在核心地位。其余图像应用 CSS translate
平移在它四周。这是我为网格中的每个图像提出的模仿公式:
translate((height + gap)*sin(0deg), (height + gap)*cos(0))translate((height + gap)*sin(60deg), (height + gap)*cos(60deg))translate((height + gap)*sin(120deg), (height + gap)*cos(120deg))translate((height + gap)*sin(180deg), (height + gap)*cos(180deg))translate((height + gap)*sin(240deg), (height + gap)*cos(240deg))translate((height + gap)*sin(300deg), (height + gap)*cos(300deg))
通过一些计算和优化后,咱们失去以下最终 CSS
.gallery { --s: 150px; /* control the size */ --g: 10px; /* control the gap */ display: grid;}.gallery > img { grid-area: 1/1; width: var(--s); aspect-ratio: 1.15; object-fit: cover; clip-path: polygon(25% 0%, 75% 0%, 100% 50% ,75% 100%, 25% 100%, 0 50%); transform: translate(var(--_x,0), var(--_y,0));}.gallery > img:nth-child(1) { --_y: calc(-100% - var(--g)); }.gallery > img:nth-child(7) { --_y: calc( 100% + var(--g)); }.gallery > img:nth-child(3),.gallery > img:nth-child(5) { --_x: calc(-75% - .87*var(--g)); }.gallery > img:nth-child(4),.gallery > img:nth-child(6) { --_x: calc( 75% + .87*var(--g)); }.gallery > img:nth-child(3),.gallery > img:nth-child(4) { --_y: calc(-50% - .5*var(--g)); }.gallery > img:nth-child(5), .gallery > img:nth-child(6) { --_y: calc( 50% + .5*var(--g)); }
每个图像都由基于这些公式的--_x
和变量转换。--_y
只有第二张图片 ( nth-child(2)) 在任何选择器中未定义,因为它位于核心。如果您决定应用不同的程序,它能够是任何图像。这是我应用的程序:
只需几行代码,咱们就失去了一个很酷的图像网格。为此,我在图像上增加了悬停的成果,让交互成果更上一层楼,代码在线预览如下:
https://code.juejin.cn/pen/71...
CSS 菱形网格
菱形是将一个正方形旋转45度。
还是雷同的 HTML,咱们首先在 CSS 中定义一个 2×2 的图像网格:
.gallery { --s: 150px; /* controls the size */ display: grid; gap: 10px; grid: auto-flow var(--s) / repeat(2, var(--s)); place-items: center;}.gallery > img { width: 100%; aspect-ratio: 1; object-fit: cover;}
而后设置旋转,请留神我如何将它们都旋转45deg,但方向相同。
.gallery { transform: rotate(45deg);}.gallery > img { transform: rotate(-45deg);}
向负方向旋转图像可避免它们与网格一起旋转,因而它们放弃笔挺。当初,咱们利用 clip-path
从它们中剪出菱形。

此时的图像并没有按咱们的预期的间距排列,咱们须要纠正图像的大小以使它们适宜在一起。否则,它们的间距会很远,以至于看起来不像图像网格。
图像在绿色圆圈的边界内,即搁置图像的网格区域的内切圆。咱们想要的是将图像放大以适宜红色圆圈,即网格区域的外接圆。
.gallery > img { width: 141%; /* 100%*sqrt(2) = 141% */ aspect-ratio: 1; object-fit: cover; transform: rotate(-45deg); clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);}
最初,还是给图像减少悬停的成果,在线代码如下:
https://code.juejin.cn/pen/71...
三角形的 CSS 网格
你当初可能晓得,最大的诀窍是找出clip-path
咱们想要的形态。对于这个网格,每个元素都有本人的clip-path
值,而最初两个网格应用统一的形态。所以,这一次,就像咱们正在解决几个不同的三角形形态,它们组合在一起造成一个矩形的图像网格。
咱们应用以下 CSS 将它们搁置在 3×2 网格中:
.gallery { display: grid; gap: 10px; grid-template-columns: auto auto auto; /* 3 columns */ place-items: center;}.gallery > img { width: 200px; /* controls the size */ aspect-ratio: 1; object-fit: cover;}/* the clip-path values */.gallery > img:nth-child(1) { clip-path: polygon(0 0, 50% 0, 100% 100% ,0 100%); }.gallery > img:nth-child(2) { clip-path: polygon(0 0, 100% 0, 50% 100%); }.gallery > img:nth-child(3) { clip-path: polygon(50% 0, 100% 0, 100% 100%, 0 100%); }.gallery > img:nth-child(4) { clip-path: polygon(0 0, 100% 0, 50% 100%, 0 100%); }.gallery > img:nth-child(5) { clip-path: polygon(50% 0, 100% 100%, 0% 100%); }.gallery > img:nth-child(6) { clip-path: polygon(0 0, 100% 0 ,100% 100%, 50% 100%); } }
最终失去的成果如下图所示:
最初一点是使两头列的宽度等于0打消图像之间的空间。咱们在菱形网格中遇到了同样的间距问题,但对咱们应用的形态采纳了不同的办法:
grid-template-columns: auto 0 auto;
最终的在线代码如下:
https://code.juejin.cn/pen/71...
比萨形态的 CSS 网格
基于下面的三角形网格通过增加简略的border-radius和overflow就能够实现另一个很酷的网格,比萨形态的 CSS 网格。
拼图格调的 CSS 网格
这次咱们将应用 CSS mask
属性来使图像看起来像拼图。
当初设置网格应该是小菜一碟,所以让咱们把注意力集中在mask
上。咱们须要两个突变来创立最终的拼图形态。一个突变创立一个圆形(绿色局部),另一个突变创立红色区域并填充半圆红色区域。
--g: 6px; /* controls the gap */--r: 42px; /* control the circular shapes */background: radial-gradient(var(--r) at left 50% bottom var(--r), green 95%, #0000), radial-gradient(calc(var(--r) + var(--g)) at calc(100% + var(--g)) 50%, #0000 95%, red) top/100% calc(100% - var(--r)) no-repeat;
两个变量管制形态。--g
变量管制网格间隙,绝对不是最重要的。重要的是思考间隙之间如何正确搁置咱们的圆圈,以便在组装整个拼图时它们完满重叠。该--r
变量则管制拼图形态的圆形局部的大小。
而后咱们应用雷同的 CSS 值并针对不同的地位稍加调整来创立其余三个形态:
此时整体拼图形态好了,但没有按咱们的预期重叠在一起。因为每个图像都被限度在它所在的网格单元中,所以当初形态有点凌乱是对的:
咱们须要通过减少图像的高度/宽度来创立溢出。从上图中,咱们必须减少第一个和第四个图像的高度,同时减少第二个和第三个图像的宽度。您可能曾经猜到咱们须要应用--r变量来减少它们。
.gallery > img:is(:nth-child(1),:nth-child(4)) { width: 100%; height: calc(100% + var(--r));}.gallery > img:is(:nth-child(2),:nth-child(3)) { height: 100%; width: calc(100% + var(--r));}
此时右边两张图片按预期展现了,但默认状况下,咱们的图像要么在右侧(如果咱们减少宽度)重叠,要么在底部(如果咱们减少高度)重叠。但这不是咱们想要的第二张和第四张图片。解决办法是在这两个图像上应用place-self: end
,最初咱们的残缺代码如下:
https://code.juejin.cn/pen/71...
最初来一个不一样的,为保障gif图加载速度,我将图片替换成纯色图像,这次咱们应用clip-path
,因为它是咱们能够动画的属性,咱们只需更新管制形态的自定义属性即可取得很酷的悬停成果。咱们设置一个自定义变量管制默认的三角形的角度,在鼠标悬停时设置该变量为0则回到失常的正方形,效果图如下:
在线代码如下:
https://code.juejin.cn/pen/71...
最初
本文通过将咱们曾经理解的无关 CSS Grid
的常识与一些附加clip-path
的mask
魔法相结合,咱们可能制作不同形态的网格布局。而且咱们每次都应用雷同的 HTML 代码!代码自身只不过是一个蕴含大量图像元素的容器!看完是不是感觉很简略很神奇呢,有趣味的同学能够本人试试看,兴许你能发明出更多乏味的网格图形。
看到最初如果感觉有用,记得点个赞珍藏起来吧,说不定哪天就用上啦。
专一前端开发,分享前端相干技术干货,公众号:南城大前端(ID: nanchengfe)