当前位置: 首页 > Web前端 > HTML

CSSCustomShapeGridLayout

时间:2023-03-28 15:59:48 HTML

你所不知道的抽奖、上传多张图片后的布局预览、朋友圈展示多张图片等这些都是正常的正方形布局。如下所示,如果图像不是正方形,而是六边形或菱形怎么办?我们该怎么做呢。事实上,我们将结合我们已经看过的CSS网格技术,并加入一些CSS剪辑路径和遮罩魔法来为您可以想象的任何形状创建精美的图像网格!相同的HTML我们将看到的大多数布局乍一看似乎很容易实现,但具有挑战性的部分是使用相同的HTML标记实现它们。我们可以使用很多包装器、div等,但本文的目标是使用相同且最少的HTML代码,仍然实现我们想要的所有不同样式的网格。也就是说,让我们从以下HTML开始:

我们只需要一个带有图像的容器。已经足够!六边形CSS网格这种形状有时被称为蜂窝状网格。首先,我们在图像上使用clip-path来创建六边形形状并将它们全部放置在相同的网格区域中,以便它们重叠。.gallery{--s:150px;/*控制尺寸*/display:grid;}.gallery>img{grid-area:1/1;宽度:var(--s);纵横比:1.15;适合对象:覆盖;剪辑路径:多边形(25%0%,75%0%,100%50%,75%100%,25%100%,050%);}![剪辑路径:多边形(25%0%,75%0%,100%50%,75%100%,25%100%,050%)](https://files.mdnice.com/user...)此时所有的图片都是六边形的并重叠。所以看起来我们只有一个六边形图像元素,但实际上有七个。下一步是将图像转换到正确放置的网格上。将其中一张图片放在中间。图像的其余部分使用CSStranslate在其周围进行翻译。这是我为网格中的每个图像想出的模拟公式: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),(高度+间隙)*cos(180deg))translate((height+gap)*sin(240deg),(height+gap)*cos(240deg))translate((height+gap)*sin(300deg),(height+gap)*cos(300deg))经过一些计算和优化,我们得到如下最终的CSS.gallery{--s:150px;/*控制大小*/--g:10px;/*控制间隙*/display:grid;}.gallery>img{grid-area:1/1;宽度:var(--s);纵横比:1.15;适合对象:覆盖;剪辑路径:多边形(25%0%,75%0%,100%50%,75%100%,25%100%,050%);转换:翻译(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...CSSdiamondgriddiamond是将一个正方形旋转45度。还是一样的HTML,我们先在CSS中定义一个2×2的图片网格:.gallery{--s:150px;/*控制尺寸*/display:grid;间隙:10px;网格:自动流var(--s)/repeat(2,var(--s));place-items:center;}.gallery>img{宽度:100%;纵横比:1;object-fit:cover;}然后设置旋转,注意我是如何将它们都旋转45度,但方向相反。.gallery{transform:rotate(45deg);}.gallery>img{transform:rotate(-45deg);}负向旋转图像可以防止它们随网格旋转,因此它们保持笔直。现在,我们应用clip-path从它们中剪出钻石。![clip-path:polygon(50%0,100%50%,50%100%,050%)](https://files.mdnice.com/user...)此时的图像不是按下在我们预期的间距对齐后,我们需要更正图像的大小以使它们适合在一起。否则,它们会相距很远,看起来不像图像网格。图像在绿色圆圈的范围内,绿色圆圈是放置图像的网格区域的内切圆。我们想要的是缩放图像以适合红色圆圈,即网格区域的外接圆。.gallery>img{宽度:141%;/*100%*sqrt(2)=141%*/纵横比:1;适合对象:覆盖;变换:旋转(-45deg);clip-path:polygon(50%0,100%50%,50%100%,050%);}最后给图片添加悬停效果,在线代码如下:https://code.juejin.cn/pen/71...CSS三角形网格你现在可能已经知道,最大的技巧是弄清楚我们想要的剪辑路径形状。对于这个网格,每个元素都有自己的clip-path值,而最后两个网格使用一致的形状。所以,这一次,就像我们要处理几个不同的三角形,它们组合在一起形成一个矩形图像网格。我们使用以下CSS将它们放置在3×2的网格中:.gallery{display:grid;间隙:10px;网格模板列:自动自动自动;/*3列*/place-items:center;}.图库>img{宽度:200px;/*控制尺寸*/aspect-ratio:1;object-fit:cover;}/*clip-path值*/.gallery>img:nth-child(1){clip-path:polygon(00,50%0,100%100%,0100%);}.gallery>img:nth-child(2){剪辑路径:多边形(00,100%0,50%100%);}.gallery>img:nth-child(3){剪辑路径:多边形(50%0,100%0,100%100%,0100%);}.gallery>img:nth-child(4){剪辑路径:多边形(00,100%0,50%100%,0100%);}.gallery>img:nth-child(5){剪辑路径:多边形(50%0,100%100%,0%100%);}.gallery>img:nth-child(6){剪辑路径:多边形(00,100%0,100%100%,50%100%);最终效果如下图所示:最后一点是让中间列的宽度等于0,消除图片之间的空格。我们在菱形网格中遇到了相同的间距问题,但对我们使用的形状采用了不同的方法:grid-template-columns:auto0auto;最终在线代码在这里:https://code.juejin.cn/pen/71...PizzaShapedCSSGrid基于上面的三角形网格,通过添加简单的border-radius和overflow可以实现另一个很酷的网格,披萨形状的CSS网格。拼图样式CSS网格这次我们将使用CSSmask属性使图像看起来像拼图。设置网格现在应该是小菜一碟,所以让我们关注蒙版。我们需要两个渐变来创建最终的拼图形状。一个渐变创建一个圆圈(绿色部分),另一个创建一个红色区域并用白色区域填充半圆。--g:6px;/*控制间距*/--r:42px;/*控制圆形*/background:radial-gradient(var(--r)atleft50%bottomvar(--r),green95%,#0000),radial-gradient(calc(var(--r)+var(--g))在calc(100%+var(--g))50%,#000095%,red)top/100%calc(100%-var(--r))no-重复;两个变量控制形状。--g变量控制网格间距,相对来说不是最重要的。重要的是要考虑如何在间隙之间正确定位我们的圆圈,以便在组装整个拼图时它们完美重叠。--r变量然后控制拼图形状的圆形部分的大小。然后,我们使用相同的CSS值创建其他三个形状,并针对不同的位置进行轻微调整:整体拼图形状现在很好,但它没有像我们预期的那样重叠。因为每个图像都被限制在它所在的网格单元中,所以现在形状有点乱是对的:我们需要通过增加图像的高度/宽度来创建溢出。从上图中,我们必须增加第一张和第四张图片的高度,同时增加第二张和第三张图片的宽度。您可能已经猜到我们需要使用--r变量来增加它们。.gallery>img:is(:nth-child(1),:nth-child(4)){宽度:100%;height:calc(100%+var(--r));}.gallery>img:is(:nth-child(2),:nth-child(3)){高度: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...最后这篇文章通过结合我们已经了解的CSSGrid和一些额外的clip-pathmask魔法,我们可以制作不同形状的网格布局。而且我们每次都使用相同的HTML代码!代码本身只不过是一个带有少量图像元素的容器!看完是不是觉得很简单很神奇呢?有兴趣的同学可以自己尝试一下,说不定还能创作出更有趣的网格图形。如果最后觉得有用,记得点赞收藏,说不定哪天你会用到。专注前端开发,分享前端相关技术干货,公众号:南城大学前端(ID:nanchengfe)