从特效入手,深入了解CSS(一):动态加载特效

不建议跳跃阅读!
这篇文章将从头开始介绍如何实现一个特效
中间偶尔会穿插一些css3或平时接触不多的css属性

首先看一看这一期的特效:

ezgif-3-a4c04cbba6

HTML部分

<div class="loader"></div>

CSS 部分

既然是一个加载特效,那么我们可以将loader垂直居中的放在页面上,这里采用的是grid布局的方法:

body {
    height:100vh;
    display:grid;
    place-content:center;
}

也许你曾经没有接触过grid布局,所以这里介绍一些常见的grid用法

grid布局

它可以将容器划分为行和列,产生单元格,然后操作项目所在的单元格,可以将grid布局看作是二维布局(平时使用的可能更为广泛的flex布局则是针对items的轴线来判定,可以看作是一维布局)

image-20220416153208113

grid-template-*

既然是二维布局,那么肯定也存在行列的设置:

  • grid-template-columns:表示列
  • grid-template-rows:表示行

以上面的图片为例,我们需要一个三行四列的布局,因此可以这样做:

grid-template-columns:100px 100px 100px;
grid-template-rows:100px 100px 100px 100px;

/* 简写 */
grid-template-columns:repeat(3,100px);
grid-template-rows:repeat(4,100px);

/* 简写 */
/* 图片中实际上是三等分列,所以可以通过repeat中的 fr 表示等分的比例关系*/
/* 比如 grid-template-columns: 1fr 2fr 3fr; 可以将列宽分成6份,三个item的长度之比为1 : 2 : 3 */
/* eg: 宽度平均分为三列等分 */
grid-template-columns:repeat(3,1fr);

grid-gap

除了可以设置行列的条数,还可以设置每个item之间的距离gap

看到这里你可能会想:“那就通过`grid-column-gap和grid-row-gap设置间隔大小就可以了”

这在以前是正确的,可是注意:根据最新标准,gap相关的grid-前缀已经删除, grid-column-gap和grid-row-gap写成column-gaprow-gap,他俩的简写grid-gap写成gap,比如:

row-gap:20px;
column-gap:20px;
/* 简写 */
gap:20px 20px;

垂直和水平布局方式

grid中控制垂直和水平布局方式的属性名称和flex布局类似:

  • 通过justify-items控制水平方向上,二维数组的每一个item中元素的对齐格式
  • 通过align-items控制垂直方向上,二维数组的每一个item中元素的对齐格式
  • 简写:place-items:xx, xx

比如:

/* 水平方向上每个item中元素左对齐 */
justify-items: start;

image-20220416155205022

  • 通过justify-content将每一列看作是一个整体,控制水平方向上,二维数组的每一列元素的对齐格式

  • 通过align-content将每一列看作是一个整体,控制垂直方向上,二维数组的每一行元素的对齐格式

  • 简写:place-content:xx, xx

    比如:

/* 水平方向上每列元素分散对齐 */
justify-content: space-around;

image-20220416155547155

好了,现在了解这些就可以了,现在再来看看之前的代码:

body {
    height:100vh;
    display:grid;
    place-content:center;
}

这段css的意思是设置body采用grid布局,并且让body中的元素在水平和垂直方向上都处于center的位置上

现在我们让loader垂直居中了,为他加一些样式:

.loader {
    width: 200px; 
    aspect-ratio: 1;
    display: grid;
    /* 为图像设置一个渐变色*/
    background: linear-gradient(135deg,#00A8C6,#8FBE00);
    /* 以向内的方式裁剪图片,消除图片的边缘*/
    clip-path: inset(10%);
}

aspect-ratio

在响应式网页设计中,保持一致的宽高比,即所谓的长宽比,对于防止布局累积偏移至关重要。在 Chromium 88、Firefox 87 和 Safari Technology Preview 版本中推出了 aspect-ratio 属性,我们有了更直接的方法来实现这一目标。

长宽比最常见的表示形式为:宽:高,摄影最常见的长宽比是 4:3 和 3:2 ,而视频和最近的消费类相机则倾向于16:9的长宽比。

随着响应式设计的出现,保持长宽比对于我们来说越来越重要。比如当我们改变显示区域大小时,div元素的长宽比也会保持不变,改变的只是长宽的数值。在一些场景下,维持长宽比显得非常的有用,比如:

/* 维持容器盒子长宽比为 16:9 */
.container {
  width: 100%;
  aspect-ratio: 16 / 9;
}

我们都知道在前端开发中经常遇到需要保持一个元素的长宽比的问题,最常见的就是我们的Img元素video元素这种本身就具有长宽比的元素。

使用auto属性,可替换元素(img、video这种本身就具有长宽比的元素)将继续保持它原本的长宽比,不会受css属性的影响。

如果希望在改变可视区域元素的长宽比时,让img元素维持原来的长宽比,可以这样做:

.container {
  width: 300px;
  /* auto元素让img元素保持原来的长宽比; 2 / 1让其他的盒子元素在大小放缩时,长宽比固定为2 / 1 */
  aspect-ratio: auto 2 / 1; 
}

好了,知道这些就够用了。这篇文章的介绍挺详细的,想要了解更多的话可以点进去看看。

我们为.loader标签设置aspect-ratio:1时可以有效地保证加载特效的1: 1展示。

回想之前的特效,正中心的.loader元素分开形成了四个小的圆圈,这些圆圈当然可以说是新增四个小的div来实现,但是这样就慢了。我们可以通过伪元素:before设置。

不过,按照以前的角度来想:“:before好像只能设置一个元素吧?“

这就错了,在css3中background属性可以设置多张背景!

css3 background特殊用法

MDN文档中的解释如下:

background 属性被指定多个背景层时,使用逗号分隔每个背景层。

每一层的语法如下:

  • 在每一层中,下列的值可以出现 0 次或 1 次:
    • <attachment>
    • <bg-image>
    • <position>
    • <bg-size>
    • <repeat-style>
  • <bg-size> 只能紧接着 <position> 出现,以"/"分割,如: “center/80%”.
  • <box> 可能出现 0 次、1 次或 2 次。如果出现 1 次,它同时设定 background-originbackground-clip。如果出现 2 次,第一次的出现设置 background-origin,第二次的出现设置 background-clip
  • <background-color> 只能被包含在最后一层。

因此,我们可以写出以下代码:

.loader:before {
    content: "";
    padding: 10%;
    /* 利用css变量的方式,将每个小圆的属性抽离出来 */
    /* 对于background来说,一定要设置no-repeat,不然就会自动复制填充了*/
    --_g: no-repeat content-box radial-gradient(50% 50%,#000 95%,#0000);
    /* 利用css3中background属性的特殊用法,设置四个圆圈 */
    background: var(--_g),var(--_g),var(--_g),var(--_g),#fff;
    /* 设置每个小圆的大小*/
    background-size: 20% 20%;
    /* 为元素添加模糊效果再增加对比度,可以实现柔和的水滴相融效果*/
    filter: blur(5px) contrast(20);
    /* 设置图片元素与父容器背景进行混合,图片会变暗 */
    /* 以韦恩图举例,这里设置的是韦恩图上的重叠部分*/
    mix-blend-mode: lighten;
}

好了,现在我们已经实现了最关键的一步:成功的创建了四个小圆,由于我们没有对它们进行定位,所以现在四个小圆的圆心重叠的位于左上角,由于采用的是padding: 10%;,可以让圆圈向下向右移动一些。

现在来实现动画效果:

@keyframes l {
  /* 0% 100%时,四个小圆分别位于上右下左 */
  0%,
  100%{background-position:top,right,bottom,left}
  /* 20% 时,上面的圆移动到中间 */
  20% {background-position:center,right ,bottom,left}
  /* 40% 时,右面的圆移动到中间 */
  40% {background-position:center,center,bottom,left}
  60% {background-position:center,center,center,left}
  80% {background-position:center,center,center,center}
}

光是小球的移动可能会有些单调,所以我们再加一些放大效果,看起来更炫酷:

@keyframes s{
  0%,
  25%,
  90% {background-size:20% 20%}
  40%,
  45%{background-size:30% 30%,20% 20%,20% 20%,20% 20%}
  60%,
  65%{background-size:40% 40%,20% 20%,20% 20%,20% 20%}
  80%{background-size:50% 50%,20% 20%,20% 20%,20% 20%}
}

最后在.loader:before中添加上动画效果:

.loader:before {
    content: "";
    padding: 10%;
    --_g: no-repeat content-box radial-gradient(50% 50%,#000 95%,#0000);
    background: var(--_g),var(--_g),var(--_g),var(--_g),#fff;
    background-size: 20% 20%;
    filter: blur(5px) contrast(20);
    mix-blend-mode: lighten;
    animation: l 3s infinite,s 3s infinite;
}

搞定,看看最终的效果吧:

ezgif-3-a4c04cbba6

完整代码

代码参考自codepen

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>黑猫几绛 |</title>
</head>
<style>

body {
    height:100vh;
    display:grid;
    place-content:center;
}

.loader {
    width: 200px; 
    aspect-ratio: 1;
    display: grid;
    background: linear-gradient(135deg,#00A8C6,#8FBE00);
    clip-path: inset(10%);
}
.loader:before {
    content: "";
    padding: 10%;
    --_g: no-repeat content-box radial-gradient(50% 50%,#000 95%,#0000);
    background: var(--_g),var(--_g),var(--_g),var(--_g),#fff;
    background-size: 20% 20%;
    filter: blur(5px) contrast(20);
    mix-blend-mode: lighten;
    animation: l 3s infinite,s 3s infinite;
}
@keyframes l {
    0%,
    100%{background-position:top,right,bottom,left}
    20% {background-position:center,right ,bottom,left}
    40% {background-position:center,center,bottom,left}
    60% {background-position:center,center,center,left}
    80% {background-position:center,center,center,center}
}
@keyframes s{
    0%,
    25%,
    90% {background-size:20% 20%}
    40%,
    45%{background-size:30% 30%,20% 20%,20% 20%,20% 20%}
    60%,
    65%{background-size:40% 40%,20% 20%,20% 20%,20% 20%}
    80%{background-size:50% 50%,20% 20%,20% 20%,20% 20%}
}

</style>
<body>
	<div class="loader"></div>
</body>
</html>

思考:现在假设有一个需求,需要实现八个小球在水平垂直的位置不停旋转,你会怎么做?

提示:用这篇文章介绍过的方法可以实现。

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值