共计 5528 个字符,预计需要花费 14 分钟才能阅读完成。
本文将介绍一种基于 CSS 变量技巧,通过正当应用 CSS 变量,实现 CSS 动画 @keyframes
的复用。
CSS 自定义变量
CSS 自定义变量大家应该都比拟相熟了,曾经不能算是新常识了,疾速过一遍。
CSS 自定义变量(CSS Variable),在之前也叫做 CSS 自定义属性,其应用形式如下:
// 申明一个变量::root{--bgColor: #000;}
这里咱们借助了下面
#12、结构性伪类
中的:root{}
伪类,在全局:root{}
伪类中定义了一个 CSS 变量,取名为--bgColor
。
定义完了之后则是应用,假如我要设置一个 div 的背景色为彩色:
.main{background:var(--bgColor);
}
这里,咱们在须要应用之前定义变量的中央,通过 var(定义的变量名)
来调用。
在 @keyframes 中应用 CSS 变量
OK,回归咱们的正题。 巧用 CSS 变量,实现动画函数复用 。
假如,咱们当初有多个元素,须要实现一个位移动画,从地位 A 位移到 地位 B,地位 A 雷同,然而地位 B 不一样,像是这样:
失常而言,因为起点不一样,咱们可能须要实现 3 个不一样的 @keyframes
,像是这样:
<ul>
<li></li>
<li></li>
<li></li>
</ul>
li:nth-child(1) {animation: move1 2s linear;}
li:nth-child(2) {animation: move2 2s linear;}
li:nth-child(3) {animation: move3 2s linear;}
@keyframes move1 {
60%,
100% {transform: translate(150px);
}
}
@keyframes move2 {
60%,
100% {transform: translate(120px);
}
}
@keyframes move3 {
60%,
100% {transform: translate(200px);
}
}
这个代码有问题吗?没有。
然而,咱们能够利用 CSS 变量,让它变得更为简洁,咱们革新一下 @keyframes
代码,将固定的位移值,变成一个变量:
@keyframes move {
60%,
100% {transform: translate(var(--dis));
}
}
因为 CSS 变量是存在作用域的,咱们能够通过 CSS 变量的形式,给每一个 li 定义一个不同的 --dis
变量,像是这样:
li:nth-child(1) {--dis: 150px;}
li:nth-child(2) {--dis: 120px;}
li:nth-child(3) {--dis: 200px;}
这样,尽管动画的完结点不一样,然而咱们利用 CSS 变量,复用了同一个 @keyframes
函数:
通过内联 style 属性传入自定义变量
除了通过在 <style>
内传入不同的自定义变量,咱们还能够通过内联 style 属性传入自定义变量。
咱们再革新一下咱们的 @keyframes
:
@keyframes move {
60%,
100% {transform: translate(var(--end));
background: var(--color);
}
}
这一次,咱们不须要通过 :nth-child()
去批改每一个 li 的 CSS,而是通过 HTML 元素的内联 style
属性,像是这样:
<ul>
<li style="--end: 150px; --color: red;"></li>
<li style="--end: 200px; --color: blue;"></li>
<li style="--end: 120px; --color: green;"></li>
</ul>
是的,每个 li 元素的 @keyframes
能够读取到每个 li 的 style
外面定义的不一样的 CSS 变量。
这样,咱们就能够失去如下成果:
残缺的代码,能够戳这里:CodePen Demo — 巧用 CSS 变量,实现动画函数复用
实战演练
上面咱们实战演练一下,上一点难度。
在很久之前,咱们实现过这样一个动画成果:
这个动画成果的实现形式在于:
- 父级元素实现一个 rotateZ(360deg) 的匀速动画
- 子级元素实现一个反向的 rotateZ(-360deg) 的匀速动画
- 给父级元素增加一个 rotateX(40deg) 的动画
因为父容器和子容器同时相同向旋转,所以子元素看上去其实和没有旋转是一样的。然而因为又增加了一个 rotateX(40deg)
动画,因而看上去就会有这样一种 3D 成果。
在之前,咱们的代码是这样的:
<div class="reverseRotate">
<div class="rotate">
</div>
</div>
.rotate {animation: rotate 5s linear infinite;}
.reverseRotate {animation: reverseRotate 5s linear infinite;}
@keyframes rotate {
0% {transform: rotateX(0deg) rotateZ(0deg);
}
50% {transform: rotateX(40deg) rotateZ(180deg);
}
100% {transform: rotateX(0deg) rotateZ(360deg);
}
}
@keyframes reverseRotate {
0% {transform: rotateZ(0deg);
}
100% {transform: rotateZ(-360deg);
}
}
能够看到,咱们这里实现了两个动画成果:
@keyframes rotate {}
父容器的旋转动画@keyframes reverseRotate {}
子容器的旋转动画
其实,这里,使用明天的技巧,咱们能够把两个动画合成为一个,利用 CSS 自定义变量进行管制。革新后更简洁的 CSS 代码如下:
.rotate {
--degZ: 360deg;
--degZMiddle: 180deg;
--degX: 30deg;
animation: rotate 5s linear infinite;
}
.reverseRotate {
--degZ: -360deg;
--degZMiddle: -180deg;
--degX: 0;
animation: rotate 5s linear infinite;
}
@keyframes rotate {
0% {transform: rotateX(0deg) rotateZ(0deg);
}
50% {transform: rotateX(var(--degX)) rotateZ(var(--degZMiddle));
}
100% {transform: rotateX(0deg) rotateZ(var(--degZ));
}
}
是的,咱们能够失去同样的成果!
残缺的代码,你能够戳这里:CodePen DEMO — Css 动画正反旋转相消
图片旋转配合容器旋转
上面,咱们再来尝试一个有意思的动画成果,图片旋转配合容器旋转。
在上述的根底上,如果咱们把子元素,改成图片,整个成果就会有意思不少,咱们略微扭转一点点代码:
<div class="reverseRotate">
<img class="rotate" src="https://picsum.photos/1000/1000?random=5" alt="">
</div>
.rotate,
.reverseRotate {
width: 60vh;
height: 60vh;
}
.reverseRotate {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 3px solid #999;
overflow: hidden;
}
.rotate {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
}
.rotate {
--degZ: 360deg;
animation: rotate 5s linear infinite;
}
.reverseRotate {
--degZ: -360deg;
animation: rotate 5s linear infinite;
}
@keyframes rotate {
0% {transform: translate(-50%, -50%) rotateZ(0deg);
}
100% {transform: translate(-50%, -50%) rotateZ(var(--degZ));
}
}
这里,咱们做了什么事件呢?
- 去掉了 3D 成果
- 给外层容器加了边框
- 内层图片基于父容器相对定位,程度垂直居中
- 内外两层容器反向旋转 360° 动画
这样,咱们就能看到,尽管内外两层容器同时在进行相同方向的旋转 360° 动画,然而外部的图片其实是静止不动的!
成果如下:
因为,外部图片的大小为父容器的 100%
,所以在旋转过程中,父容器会有显著的无奈包裹住整个图片的状况。
这个很好解决,咱们只须要把图片大小调整大一点:
// ... 其它代码不变
.rotate {
width: 150%;
height: 150%;
}
.rotate {
--degZ: 360deg;
animation: rotate 5s linear infinite;
}
失常而言,对于正方形容器,外部图片设置到 141%
即可满足父容器旋转过程,能够始终包裹住图片的成果。那么,咱们就能失去这样一种成果:
残缺的代码,你能够戳这里:CodePen Demo — Css 动画正反旋转相消
Gird 布局配合正反旋转动画
当然,上述当只有一个容器的时候,整个动画成果还不够震撼。
如果咱们能够把这个成果交融进整个布局的动画之中,整个成果又会齐全不一样。
在 Rotating gallery with CSS scroll-driven animations 这篇文章中,作者提供了一种十分奇妙的思路,将 Grid 布局动画与上述动画成果奇妙的联合了起来。
首先,咱们利用 Gird 布局,实现这样一个简略的网格布局构造:
<div class="container">
<div class="A">
<img src="https://picsum.photos/600/600?random=1" alt=""></div>
<div class="B">
<img src="https://picsum.photos/600/600?random=2" alt=""></div>
<div class="C">
<img src="https://picsum.photos/600/600?random=3" alt=""></div>
<div class="D">
<img src="https://picsum.photos/600/600?random=4" alt=""></div>
<div class="E">
<img src="https://picsum.photos/600/600?random=5" alt=""></div>
</div>
.container {
width: 60vmin;
height: 60vmin;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
gap: 4px;
grid-template-areas:
"E B B"
"E A C"
"D D C";
}
.container > div {
border: 3px solid #431312;
border-radius: 5px;
}
.A {grid-area: A;}
.B {grid-area: B;}
.C {grid-area: C;}
.D {grid-area: D;}
.E {grid-area: E;}
成果如下:
接下来,咱们要做的,就是联合下面的知识点,容器滚动起来,图片反向滚动起来,配合一些 tranfrom 变换。
有了下面的铺垫,上面的新增的代码就十分好了解了:
.container > div img {
--scale: 1;
--rotation: -360deg;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 260%;
height: 260%;
object-fit: cover;
object-position: center;
}
.container,
.container > div img {animation: 10s scale-up both ease-in-out infinite alternate;}
@keyframes scale-up {
0% {transform: translate(-50%, -50%) scale(var(--scale)) rotate(0deg);
}
100% {transform: translate(-50%, -50%) scale(1) rotate(var(--rotation));
}
}
这样,咱们就失去了一个高级感拉满的网格旋转动画:
留神,这里咱们仍旧是通过 CSS 自定义变量,在不同元素间,复用了同一个动画 @keyframes
函数。
残缺的代码,你能够戳这里:CodePen Demo — Grid 图片旋转动画 & 应用 CSS 变量复用动画函数
最初
好了,本文到此结束,心愿本文对你有所帮忙 :)
想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 — iCSS 前端趣闻 😄
更多精彩 CSS 技术文章汇总在我的 Github — iCSS,继续更新,欢送点个 star 订阅珍藏。
如果还有什么疑难或者倡议,能够多多交换,原创文章,文笔无限,满腹经纶,文中若有不正之处,万望告知。