不建议跳跃阅读!
这篇文章将从头开始介绍如何实现一个特效
中间偶尔会穿插一些css3或平时接触不多的css属性
首先看一看这一期的特效:
<div class="loader">div>
既然是一个加载特效,那么我们可以将loader
垂直居中的放在页面上,这里采用的是grid布局的方法:
body {
height:100vh;
display:grid;
place-content:center;
}
也许你曾经没有接触过grid布局
,所以这里介绍一些常见的grid用法
它可以将容器划分为行和列,产生单元格,然后操作项目所在的单元格,可以将grid布局看作是二维布局(平时使用的可能更为广泛的flex布局
则是针对items的轴线来判定,可以看作是一维布局)
既然是二维布局,那么肯定也存在行列的设置:
以上面的图片为例,我们需要一个三行四列的布局,因此可以这样做:
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);
除了可以设置行列的条数,还可以设置每个item之间的距离gap
看到这里你可能会想:“那就通过`grid-column-gap和grid-row-gap设置间隔大小就可以了”
这在以前是正确的,可是注意:根据最新标准,gap相关的grid-前缀已经删除, grid-column-gap和grid-row-gap写成column-gap
和row-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;
通过justify-content
将每一列看作是一个整体,控制水平方向上,二维数组的每一列元素的对齐格式
通过align-content
将每一列看作是一个整体,控制垂直方向上,二维数组的每一行元素的对齐格式
简写:place-content:xx, xx
比如:
/* 水平方向上每列元素分散对齐 */
justify-content: space-around;
好了,现在了解这些就可以了,现在再来看看之前的代码:
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%);
}
在响应式网页设计中,保持一致的宽高比,即所谓的长宽比,对于防止布局累积偏移至关重要。在 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
属性可以设置多张背景!
MDN文档中的解释如下:
background
属性被指定多个背景层时,使用逗号分隔每个背景层。每一层的语法如下:
- 在每一层中,下列的值可以出现 0 次或 1 次:
只能紧接着
出现,以"/"分割,如: “
center/80%
”.可能出现 0 次、1 次或 2 次。如果出现 1 次,它同时设定
background-origin
和background-clip
。如果出现 2 次,第一次的出现设置background-origin
,第二次的出现设置background-clip
。只能被包含在最后一层。
因此,我们可以写出以下代码:
.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;
}
搞定,看看最终的效果吧:
代码参考自codepen
黑猫几绛 |
"loader">
思考:现在假设有一个需求,需要实现八个小球在水平垂直的位置不停旋转,你会怎么做?
提示:用这篇文章介绍过的方法可以实现。