那些你不知道的css自定义形状网格布局3(代码片段)

author author     2022-12-13     795

关键词:

基于CSS自定义网格已发布第一部分和第二部分,本文将开始第三部分探讨更多的奇特自定义形状,与之前的文章一样,核心还是基于CSS grid,clip 和 mask来自定义网格形状布局。

三部分文章不一定要按照顺序阅读,之间没有强制的关联关系,但是可以看看之前的文章,了解作者是如何完成当前的效果,接下来开始我们的第一个案例。

案例一 图片库

以上效果图我们的HTML代码如下:

<div class="gallery">
  <img src="..." alt="...">
  <img src="..." alt="...">
  <img src="..." alt="...">
  <img src="..." alt="...">
</div>

本系列的主要挑战都是尽可能使用少量的html标签,后续的示例也是使用相同的html代码,不会有其他的div,嵌套元素等,仅需要如上的代码结构。 然后再来看看CSS代码:

.gallery 
  --g: 6px; /* the gap */

  display: grid;
  width: 450px; /* the size */
  aspect-ratio: 1; /* equal height */
  grid: auto-flow 1fr / repeat(3, 1fr);
  gap: var(--g);

.gallery img:nth-child(2) 
  grid-area: 1 / 2 / span 2 / span 2;

.gallery img:nth-child(3) 
  grid-area: 2 / 1 / span 2 / span 2;

基于上面的CSS是可以看出把整个盒子分为了一个3 ✖️ 3 的网格,第二个和第三个图像设定了相应的网格属性,第一个和最后一个图像将自动围绕布局。

这里的核心代码是 grid: auto-flow 1fr / repeat(3, 1fr);,这里使用了CSS网格简写属性,相当于以下代码:

grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 1fr;

简写属性对应每个属性的值可以通过浏览器DevTools展开看到以下数据。

此同样适用于网格区域属性,当我们定义CSS网格面积为:

grid-area: 1 / 2 / span 2 / span 2;

最终对应的具体属性值如下:

grid-row-start: 1; /* 从第一行开始 */
grid-column-start: 2; /* 从第二列开始 */
grid-row-end: span 2; /* 占据两行 */
grid-column-end: span 2; /* 占据两列 */

基于以上网格区域声明,即得到以下结果: 我们的第二张和第三张图像在中间重叠,这是故意将它们重叠在一起,这样就可以使用 clip-path,从两个图像中裁剪出一部分,得到最终的效果:

们可以使用CSS clip-path 属性裁剪第二张图片(img:nth-child(2))的左下角:

clip-path: polygon(0 0, 100% 0, 100% 100%, calc(50% + var(--g) / 4) 100%, 0 calc(50% - var(--g) / 4))

裁剪第三张图片(img:nth-child(3))的右上角:

clip-path: polygon(0 0, calc(50% - var(--g) / 4) 0, 100% calc(50% + var(--g) / 4), 100% 100%, 0 100%);

如果不理解 clip-path 的用法,我有一篇文章详细介绍如何使用这种技术。

案例二 图片分割效果

接下来我们基于上面用到的裁剪图片技术结合鼠标悬停完成一个不错的交互效果。

这个效果的网格配置没有上一张强烈,因为我们只需要两张重叠的图像:

.gallery 
  display: grid;

.gallery > img 
  grid-area: 1 / 1;
  width: 350px; /* the size */
  aspect-ratio: 1; /* equal height */

悬停效果依赖于动画剪辑路径。我们将详细剖析第一个图像的代码,看看它是如何实现的,然后用更新的值将相同的代码应用到第二个图像。仔细分析可以得出挣个动画过程中出现有三种不同的状态:

    1. 当图像没有鼠标悬停时,将显示每个图像的一半。
    1. 当鼠标悬停在第一张图像上时,它会更完全地显示出来,但会保留一个小角。
    1. 当鼠标悬停在第二张图片上时,第一张图片只有一个小三角形可见。

在每种状态下,我们都有一个三角形。这意味着我们需要一个三点多边形作为clip-path的值。

肉眼看确实是一个带有切角的正方形,但如果我们仔细看,我们可以看到一个“隐藏”的三角形,给图像添加一个方框阴影的效果就比较清晰了。

box-shadow: 0 0 0 200px red;

这是什么原理呢?原理就是 clip-path 接受0%-100%范围之外的值,这将允许我们创建“溢出”元素本身的形状。这样我们只需要使用三个点,而不是使用五个点,就可以完成我们期望的效果。最终图片的 clip-path 属性值如下所示:

.gallery > img:first-child 
  clip-path: polygon(0 0, calc(100% + var(--_p)) 0 , 0 calc(100% + var(--_p)))

.gallery > img:last-child 
  clip-path: polygon(100% 100%, 100% calc(0% - var(--_p)), calc(0% - var(--_p)) 100%)

这里增加了--_p变量,即两图之间的间隙距离。基于此来优化代码,因为我们添加了悬停过渡。我们不需要更新整个clip-path,而只更新此变量即可以获得动画效果。 最后是增加悬停后的完整代码:

.gallery 
  --g: 8px; /* the gap */

.gallery > img 
  /* etc. */
  --_p: calc(-1 * var(--g));
  transition: .4s .1s;

.gallery:hover > img:last-child,
.gallery:hover > img:first-child:hover
  --_p: calc(50% - var(--g));

.gallery:hover > img:first-child,
.gallery:hover > img:first-child:hover + img 
  --_p: calc(-50% - var(--g));

案例三 饼图效果

这个效果我们增加难度,和上面的效果类似,但增加到四个图像,而不是两个。 每个图像是一个圆的四分之一,鼠标悬停时,基于动画将一个图像转换为一个完整的圆,覆盖其余的图像。看起来是不是很炫酷呢,接下来开始具体的实现过程。

首先给整个元素增加 border-radius: 50%使其变为圆形。 然后是针对每个图像设置 clip-path 值,clip-path由七个点组成,其中三个点位于固定位置,如上图所示,默认就是一个三角形。当悬停时,修改剩余几个点的数值并加上过渡动画。

transition: transform .2s, clip-path .3s .2s, z-index 0s;

但是当它运行缓慢时,效果看起来不那么酷,但我们可以看到剪辑路径如何在形状之间进行变化的。以下是第一个图像的代码,其他的几个图像类似,只是对应方向的数值不同:

.gallery > img:nth-child(1) 
  clip-path: polygon(50% 50%, calc(50% * var(--_i, 0)) calc(120% * var(--_i, 0)), 0 calc(100% * var(--_i, 0)),0 0, 100% 0, 100% calc(100% * var(--_i, 0)), calc(100% - 50% * var(--_i, 0)) calc(120% * var(--_i, 0)));

.gallery > img:hover 
 --_i: 1;

这里还是像往常一样,我使用一个变量来优化代码。变量将在0和1之间切换来达到更新多边形的效果。

案例四 多图镶嵌效果

这是一种艺术风格,各种各样的图像以不同的形状组合在一起。这个效果利用我们今天使用的CSS完全可以胜任! 基于上面的效果图,我们来分析每个图像的位置和大小。我们需要确定网格需要多少列和行数:

    1. 我们有两个大的图像放置在彼此旁边,每个填充一半的网格宽度和整个网格高度。这意味着可能需要 两列 和 单行。
    1. 中间的图像与另外两个图像重叠。这意味着我们需要 四列 和 单行。
    1. 最后两个图像各填充一半网格,就像前两个图像一样。但它们只有网格高度的一半。我们可以使用现有的列,但我们需要 两排。

这仅仅是我理解它的方式。我相信还有其他的配置可以得到同样的布局,有兴趣的同学可以用自己的思路实现看看。 基于以上我们定义的网格,然后将图像放在对应的网格上面:

.gallery 
  display: grid;
  grid: repeat(2, 1fr) / repeat(4, 1fr); 
  aspect-ratio: 2;

.gallery img:nth-child(1) 
  grid-area: 1 / 1 / span 2 / span 2;

.gallery img:nth-child(2) 
  grid-area: 1 / 2 / span 2 / span 2;

.gallery img:nth-child(3) 
  grid-area: span 2 / span 2 / -1 / -1;

.gallery img:nth-child(4) 
  grid-area: 2 / 1 / span 1 / span 2;

.gallery img:nth-child(5) 
  grid-area: span 1 / span 2 / -1 / -1;

看到这相信你已经发现我们使用相同方法的例子。我们定义了一个网格并将图像显式地放置在网格上,使用网格区域使图像重叠。最后将重叠的部分进行裁剪达到最终的目的。接下来就是裁剪的部分,我们总共有四个三角形和一个菱形。

完整代码:

.gallery img:nth-child(1) 
  grid-area: 1/1/span 2/span 2;
  clip-path: polygon(0 0,100% 0,0 100%);

.gallery img:nth-child(2) 
  grid-area: 1/2/span 2/span 2;
  clip-path: polygon(50% 0,100% 50%,50% 100%,0 50%);

.gallery img:nth-child(3) 
  grid-area: span 2/span 2/-1/-1;
  clip-path: polygon(0 0,100% 0,100% 100%);

.gallery img:nth-child(4) 
  grid-area: 2/1/span 1/span 2;
  clip-path: polygon(50% 0,100% 100%,0 100%);

.gallery img:nth-child(5) 
  grid-area: span 1/span 2/-1/-1;
  clip-path: polygon(50% 0,100% 100%,0 100%);

基于这个效果可以引出一个更为复杂的多图排版效果,此效果没有上面的对称效果,实现起来相对复杂一点。 但是核心的实现过程都是一样的,可以将整体按以下网格布局进行排列,有兴趣的同学可以自己实现看看。

总结

在整个系列中,我们探索了许多不同类型的图像网格,从基本的东西到我们今天制作的复杂马多图镶嵌。这里面的大量的CSS裁剪实践经验希望在你的项目中可以用到这些经验!

整体代码在线效果:https://code.juejin.cn/pen/7175445958677758009

看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

8.13-8.19博客精彩回顾

一、优秀文章推荐1.​​那些你不知道的CSS自定义形状网格布局​​2.​​java之继承精选​​3.​​Java8重构传统设计模式,是真的优雅!​​4.​​实战Node.js之GET/POST请求在Web应用架构在客户端的使用​​5.​​【Docker那些事儿... 查看详情

安卓讲课笔记3.4网格布局(代码片段)

...、创建安卓应用2、准备背景图片3、字符串资源文件4、自定义边框配置文件5、主布局资源文件6、启动应用&# 查看详情

那些你不知道的炫酷导航交互效果(代码片段)

基于上次发布的那些你不知道的炫酷按钮交互效果反馈比较好,后续将继续收集那些炫酷的交互效果,希望可以给你的项目添砖加瓦,更上一层楼。那些你不知道的炫酷交互效果系列:那些你不知道的炫酷按钮交互效果那些你不... 查看详情

那些你不知道的炫酷开关交互效果(12种)(代码片段)

本文将继续更新那些炫酷交互效果系列文章,今天带来的是有关toggle开关相关的组件。以下是本次文章涉及到的开关组件总览图,总计收集12款不同交互效果,相信总有一款适合你。那些你不知道的炫酷交互效果系列:那些你不... 查看详情

matplotlib使用gridspec和其他功能自定义图形布局(代码片段)

如何创建轴的网格状组合。subplots()也许用于创建图形和轴的主要功能。它也类似于matplotlib.pyplot.subplot(),但是会立即在图形上创建并放置所有轴。GridSpec指定将放置子图的网格的几何形状。需要设置网格的行数和列数。可选地,... 查看详情

如何将自定义网格添加到 ImageItem?

...示例相同:aitoff-hammer地图投影:.问题是,我的图像没有那些网格线。我已经验证了将像素值转换为纬度/经度坐标的代码是否有效,但 查看详情

css3自适应布局单位vw,vh,你知道多少?(代码片段)

视口单位(Viewportunits)什么是视口? 在桌面端,视口指的是在桌面端,指的是浏览器的可视区域;而在移动端,它涉及3个视口:LayoutViewport(布局视口),VisualViewport(视觉视口),IdealViewport(理想视口)。视口单位中的“视... 查看详情

「译」foreach循环中你不知道的3件事(代码片段)

前言本文925字,阅读大约需要7分钟。总括:forEach循环中你不知道的3件事。原文地址:3thingsyoudidn’tknowabouttheforEachloopinJS公众号:「前端进阶学习」,回复「666」,获取一揽子前端技术书籍自弃者扶不起,自强者击不倒。正文你... 查看详情

css自定义网格css1/5与bootstrap断点(代码片段)

查看详情

字符串,那些你不知道的事(代码片段)

 Everythingyouthoughtyouknewaboutstringsiswrong.也许你会诧异,字符串有什么难的,即便遇到乱码的情况随便Google下就能找到解决方法,但是这样你不觉得有种被动的感觉嘛,我觉得和学习任何东西一样,学习编程首要是学习其思想,... 查看详情

你不知道的css---position小技巧(代码片段)

众所周时"position:sticky;"是粘性布局,相当于sticky与fixed的组合。但他的细节和妙用,未必人人皆知。所以记录下我这一周的学习总结,供大家参考使用。回顾positionvaluesposition中目前有五个值分别是static、relative、absolute、f... 查看详情

那些你不知道的kotlin冷知识(代码片段)

Lambda表达式Lambda固然好用,但是你知道Kotlin是如何实现的吗?kotlin代码funfoo(item:Int)=print(item)转换为java字节码@NotNullpublicfinalFunction0foo(finalintitem)return(Function0)(newFunction0()//$FF:syntheticm 查看详情

springcloudzuul那些你不知道的功能点(代码片段)

本文摘自于《SpringCloud微服务入门实战与进阶》一书。1./routes端点当@EnableZuulProxy与SpringBootActuator配合使用时,Zuul会暴露一个路由管理端点/routes。借助这个端点,可以方便、直观地查看以及管理Zuul的路由。将所有端点都暴露出来... 查看详情

你不知道的css单位(代码片段)

CSS中大部分属性值都有对应的量词单位,常见的如描述盒模型尺寸的width,height,margin,padding,border,又比如CSS3中的transform属性的一些值。下面的导图中基本上包括了所有的单位,下面将详细介绍它们的定义及使用方式。?一、长度单... 查看详情

3.为自定义控件添加属性(代码片段)

...;属性"两个字而言我想大家已近再熟悉不过了如果你说你不知道那我只能说难道你没有用C#写过类没有在里面定义过属性么是的没 查看详情

grid布局(代码片段)

...局使我们能够比以往任何时候都可以更灵活构建和控制自定义网格;能够将网页分成具有简单属性的行和列来完成我们需要的网格布局。CSSGrid布局由两个核心组成部分是wrapper(父元素)和items(子元素)。wrapper是实际的grid(网格)... 查看详情

详解css中的网格布局,小程序中实现预约列表功能(代码片段)

...组成,我们在画图软件里标一下行、列及轨道的号码知道这个布局的构成后,我们就需要 查看详情

详解css中的网格布局,小程序中实现预约列表功能(代码片段)

...组成,我们在画图软件里标一下行、列及轨道的号码知道这个布局的构成后,我们就需要 查看详情