本文翻译自 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)) 在任何选择器中未定义,因为它位于中心。如果您决定使用不同的顺序,它可以是任何图像。这是我使用的顺序:
只需几行代码,我们就得到了一个很酷的图像网格。为此,我在图像上添加了悬停的效果,让交互效果更上一层楼,代码在线预览如下:
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%); }
最后,还是给图像增加悬停的效果,在线代码如下:code.juejin.cn/pen/7132464…