We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
本文将介绍一种基于 CSS 变量技巧,通过合理使用 CSS 变量,实现 CSS 动画 @keyframes 的复用。
@keyframes
CSS 变量大家应该都比较熟悉了,已经不能算是新知识了,快速过一遍。
CSS 变量(CSS Variable),在之前也叫做 CSS 自定义属性,其使用方式如下:
// 声明一个变量: :root{ --bgColor: #000; }
这里我们借助了上面 #12、结构性伪类 中的 :root{ } 伪类,在全局 :root{ } 伪类中定义了一个 CSS 变量,取名为 --bgColor 。
#12、结构性伪类
:root{ }
--bgColor
定义完了之后则是使用,假设我要设置一个 div 的背景色为黑色:
.main{ background:var(--bgColor); }
这里,我们在需要使用之前定义变量的地方,通过 var(定义的变量名) 来调用。
var(定义的变量名)
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 变量,像是这样:
--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 属性,像是这样:
:nth-child()
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 变量,实现动画函数复用
下面我们实战演练一下,上一点难度。
在很久之前,我们实现过这样一个动画效果:
这个动画效果的实现方式在于:
由于父容器和子容器同时相反向旋转,所以子元素看上去其实和没有旋转是一样的。但是由于又添加了一个 rotateX(40deg) 动画,因此看上去就会有这样一种 3D 效果。
rotateX(40deg)
在之前,我们的代码是这样的:
<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)); } }
这里,我们做了什么事情呢?
这样,我们就能看到,虽然内外两层容器同时在进行相反方向的旋转 360° 动画,但是内部的图片其实是静止不动的!
效果如下:
由于,内部图片的大小为父容器的 100%,所以在旋转过程中,父容器会有明显的无法包裹住整个图片的情况。
100%
这个很好解决,我们只需要把图片大小调整大一点:
// ... 其它代码不变 .rotate { width: 150%; height: 150%; } .rotate { --degZ: 360deg; animation: rotate 5s linear infinite; }
正常而言,对于正方形容器,内部图片设置到 141% 即可满足父容器旋转过程,可以一直包裹住图片的效果。那么,我们就能得到这样一种效果:
141%
完整的代码,你可以戳这里:CodePen Demo -- Css动画正反旋转相消
当然,上述当只有一个容器的时候,整个动画效果还不够震撼。
如果我们可以把这个效果融合进整个布局的动画之中,整个效果又会完全不一样。
在 Rotating gallery with CSS scroll-driven animations 这篇文章中,作者提供了一种非常巧妙的思路,将 Grid 布局动画与上述动画效果巧妙的结合了起来。
首先,我们利用 Grid 布局,实现这样一个简单的网格布局结构:
<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 订阅收藏。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
The text was updated successfully, but these errors were encountered:
你好,图片旋转配合容器旋转小结中,旋转结构体可以考虑不动,而图片元素则作为子元素。
<div class="reverseRotate"> <div class="rotate"> <img src="https://picsum.photos/1000/1000?random=5" alt=""> </div> </div>
样式部分相对可能会精简清晰一些。
.rotate, .reverseRotate { width: 60vh; height: 60vh; } .reverseRotate { border: 3px solid #999; overflow: hidden; } .rotate { --degZ: 360deg; animation: rotate 5s linear infinite; } .reverseRotate { --degZ: -360deg; animation: rotate 5s linear infinite; } @keyframes rotate { 0% { transform: rotateZ(0deg); } 100% { transform: rotateZ(var(--degZ)); } }
图片大小可调整为。
img { width: 100%; height: 100%; transform: scale(1.5); }
Sorry, something went wrong.
太强了
No branches or pull requests
本文将介绍一种基于 CSS 变量技巧,通过合理使用 CSS 变量,实现 CSS 动画
@keyframes
的复用。CSS 变量
CSS 变量大家应该都比较熟悉了,已经不能算是新知识了,快速过一遍。
CSS 变量(CSS Variable),在之前也叫做 CSS 自定义属性,其使用方式如下:
定义完了之后则是使用,假设我要设置一个 div 的背景色为黑色:
这里,我们在需要使用之前定义变量的地方,通过
var(定义的变量名)
来调用。在 @Keyframes 中使用 CSS 变量
OK,回归我们的正题。巧用 CSS 变量,实现动画函数复用。
假设,我们现在有多个元素,需要实现一个位移动画,从位置 A 位移到 位置 B,位置 A 相同,但是位置 B 不一样,像是这样:
正常而言,由于终点不一样,我们可能需要实现 3 个不一样的
@keyframes
,像是这样:这个代码有问题吗?没有。
但是,我们可以利用 CSS 变量,让它变得更为简洁,我们改造一下
@keyframes
代码,将固定的位移值,变成一个变量:由于 CSS 变量是存在作用域的,我们可以通过 CSS 变量的方式,给每一个 li 定义一个不同的
--dis
变量,像是这样:这样,虽然动画的结束点不一样,但是我们利用 CSS 变量,复用了同一个
@keyframes
函数:通过内联 style 属性传入自定义变量
除了通过在
<style>
内传入不同的自定义变量,我们还可以通过内联 style 属性传入自定义变量。我们再改造一下我们的
@keyframes
:这一次,我们不需要通过
:nth-child()
去修改每一个 li 的 CSS,而是通过 HTML 元素的内联style
属性,像是这样:是的,每个 li 元素的
@keyframes
可以读取到每个 li 的style
里面定义的不一样的 CSS 变量。这样,我们就可以得到如下效果:
完整的代码,可以戳这里:CodePen Demo -- 巧用 CSS 变量,实现动画函数复用
实战演练
下面我们实战演练一下,上一点难度。
在很久之前,我们实现过这样一个动画效果:
这个动画效果的实现方式在于:
由于父容器和子容器同时相反向旋转,所以子元素看上去其实和没有旋转是一样的。但是由于又添加了一个
rotateX(40deg)
动画,因此看上去就会有这样一种 3D 效果。在之前,我们的代码是这样的:
可以看到,我们这里实现了两个动画效果:
@keyframes rotate {}
父容器的旋转动画@keyframes reverseRotate {}
子容器的旋转动画其实,这里,运用今天的技巧,我们可以把两个动画合成为一个,利用 CSS 自定义变量进行控制。改造后更简洁的 CSS 代码如下:
是的,我们可以得到同样的效果!
完整的代码,你可以戳这里:CodePen DEMO -- Css动画正反旋转相消
图片旋转配合容器旋转
下面,我们再来尝试一个有意思的动画效果,图片旋转配合容器旋转。
在上述的基础上,如果我们把子元素,改成图片,整个效果就会有意思不少,我们稍微改变一点点代码:
这里,我们做了什么事情呢?
这样,我们就能看到,虽然内外两层容器同时在进行相反方向的旋转 360° 动画,但是内部的图片其实是静止不动的!
效果如下:
由于,内部图片的大小为父容器的
100%
,所以在旋转过程中,父容器会有明显的无法包裹住整个图片的情况。这个很好解决,我们只需要把图片大小调整大一点:
正常而言,对于正方形容器,内部图片设置到
141%
即可满足父容器旋转过程,可以一直包裹住图片的效果。那么,我们就能得到这样一种效果:完整的代码,你可以戳这里:CodePen Demo -- Css动画正反旋转相消
Grid 布局配合正反旋转动画
当然,上述当只有一个容器的时候,整个动画效果还不够震撼。
如果我们可以把这个效果融合进整个布局的动画之中,整个效果又会完全不一样。
在 Rotating gallery with CSS scroll-driven animations 这篇文章中,作者提供了一种非常巧妙的思路,将 Grid 布局动画与上述动画效果巧妙的结合了起来。
首先,我们利用 Grid 布局,实现这样一个简单的网格布局结构:
效果如下:
接下来,我们要做的,就是结合上面的知识点,容器滚动起来,图片反向滚动起来,配合一些 tranfrom 变换。
有了上面的铺垫,下面的新增的代码就非常好理解了:
这样,我们就得到了一个高级感拉满的网格旋转动画:
注意,这里我们依旧是通过 CSS 自定义变量,在不同元素间,复用了同一个动画
@keyframes
函数。完整的代码,你可以戳这里:CodePen Demo -- Grid 图片旋转动画 & 使用 CSS 变量复用动画函数
最后
好了,本文到此结束,希望本文对你有所帮助 :)
想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 -- iCSS前端趣闻 😄
更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
The text was updated successfully, but these errors were encountered: