交互式CSS过渡指南

2021-02-27 09:12:03

网络动画的世界已成为工具和技术的庞大丛林。诸如GSAP,Framer Motion和React Spring之类的库如雨后春笋般涌现,以帮助我们向DOM添加运动。

不过,最基本,最关键的部分是谦虚的CSS过渡。它是大多数前端开发人员学习的第一个动画工具,并且是主力军。即使是最灰暗,风化的动画老手也经常可以使用此工具。

这个主题的深度令人惊讶。在本教程中,我们将深入研究并了解有关CSS过渡的更多信息,以及如何使用它们来创建华丽,优美的动画。

当用户的鼠标停在按钮上方时,此代码段使用:hover伪类来指定其他CSS声明,类似于JavaScript中的onMouseEnter事件。

为了向上移动元素,我们使用了transform:translateY(-10px)。虽然我们本可以使用margin-top来实现,但transform:translate是完成这项工作的更好工具。我们待会儿会为什么。

默认情况下,CSS中的更改是即时发生的。眨眼间,我们的按钮已移至新位置!这与自然世界是不协调的,自然世界是逐渐发生的事情。

我们可以指示浏览器使用恰当命名的transition属性从一种状态插值到另一种状态:

过渡属性具有特殊值:全部。当全部指定后,任何更改的CSS属性都将被转换。

使用此值可能很诱人,因为如果我们要为多个属性设置动画,它可以节省很多键入时间,但是我建议不要使用它。

随着产品的发展,您(或团队中的某人)很可能会在将来的某个时候更新此代码。意外的动画可能会漏掉。

动画就像盐一样:太多会破坏盘子。使用我们设置动画的属性需要非常精确。

当我们告诉元素从一个位置转换到另一个位置时,浏览器需要确定每个" intermediary"框架应该看起来像。

例如:假设我们要在1秒钟的时间内从左向右移动一个元素。平滑的动画应以60fps的速度运行,这意味着我们需要在起点和终点之间提出60个单独的位置。

为了弄清这里发生的事情:每个褪色的圆圈代表一个时刻。当圆从左向右移动时,这些是向用户显示的框架。就像一本活页簿。

在此动画中,我们正在使用线性定时功能。这意味着元素以恒定的速度移动。我们的圈子每帧移动相同的量。

CSS提供了一些计时功能。我们可以使用transition-timing-function属性指定要使用的哪一个:

线性很少是最佳选择-毕竟,在现实世界中,几乎没有任何东西会以这种方式移动。好的动画模仿自然世界,所以我们应该选择有机的东西!

缓解就像狂放的公牛冲入来一样,但是它耗尽了精力。最后,它像沉睡的乌龟一样刺痛着。

尝试使用时间轴进行擦洗;请注意,在最初的几帧中运动非常剧烈,并且在运动结束时变得多么微妙。

如果要绘制元素随时间的位移,它看起来像这样:

您什么时候使用缓释法?它是从屏幕外进入某些内容(例如出现模态)时最常用的方法。它产生的效果是,有些东西从远方进入,并摆在用户面前。

正如我们所看到的,缓动对于从屏幕外进入的事物很有用。相反,easy-in自然很有用:将某些东西移出视口范围。

当某些东西进入和退出视口(例如模态)时,此组合很有用。我们将很快介绍如何混合和匹配计时功能。

注意,缓入对于以元素离屏或不可见结束的动画非常有用。否则,突然停止可能会令人讨厌。

我发现该曲线对于循环中发生的任何事情(例如,元素淡入淡出,一遍又一遍)最有用。

这是线性上的一大进步,但是在您将它应用于所有内容之前,让我们再来看一个选择。

如果在过渡时我愿意与CSS语言作者联系,那么这种简便性就得不到很好的称呼。它根本不是描述性的;从字面上看,所有计时功能都是一种轻松的选择!

撇开那只顽皮,轻松真棒。与渐入渐出不同,它不是对称的。它具有短暂的加速和大量的减速功能。

easy是默认值-如果您未指定计时功能,则会使用easy。老实说,这对我来说是正确的。在大多数情况下,轻松是一个不错的选择。如果某个元素移动了,并且没有进入或退出视口,那么轻松通常是一个不错的选择。

如果提供的内置选项不适合您的需求,则可以使用三次贝塞尔曲线定时功能定义自己的自定义缓动曲线!

到目前为止,我们看到的所有值实际上只是此三次贝塞尔曲线函数的预设。它需要4个数字,代表2个控制点。

贝塞尔曲线确实很漂亮,但它们超出了本教程的范围。我很快就会写关于它们的更多信息!

同时,您可以使用Lea Verou的出色帮助器开始创建自己的Bézier计时功能:

找到满意的动画曲线后,请点击顶部的“复制”,然后将其粘贴到CSS中!

您还可以从这套扩展的计时功能中进行选择。尽管要当心:一些比较古怪的选项在CSS中无法使用。

从自定义贝塞尔曲线开始时,很难想像出自然的曲线。但是,通过一些实践,这是一种难以置信的表达工具。

我要坦白:上面的演示,展示了不同的计时功能,被夸大了。

实际上,计时功能(如“缓入”)比所描绘的要微妙得多,但我想强调其效果,以使其更易于理解。三次方贝塞尔计时功能使之成为可能!

之前,我们提到动画应该以60fps的速度运行。但是,当我们进行数学运算时,我们意识到这意味着浏览器仅用16.6毫秒即可绘制每个帧。确实时间不多了;供参考,眨眼大约需要100ms-300ms!

如果我们的动画在计算上过于昂贵,它将显得僵硬而结结巴巴。帧会掉落,因为设备无法跟上。

实际上,性能不佳通常会采用可变帧速率的形式,因此这并不是一个完美的模拟。

动画性能是一个令人惊讶的深层且有趣的领域,远远超出了本入门教程的范围。但是,让我们介绍一下绝对关键的,需要了解的部分:

一些CSS属性要比其他属性昂贵得多。例如,高度是非常昂贵的属性,因为它会影响布局。当元素的高度缩小时,会引起连锁反应。它的所有兄弟姐妹也需要向上移动,以填补空间!

其他属性(例如背景色)的动画制作成本较高。它们不会影响布局,但是它们确实需要在每个框架上涂上一层新鲜的油漆,这并不便宜。

动画和透明度这两个属性非常便宜。如果动画当前正在调整诸如width或left之类的属性,则可以通过移动它进行变换来极大地改善它(尽管始终不可能获得完全相同的效果)。

确保在您的网站/应用定位的最低端设备上测试动画。您的开发机器可能比它快许多倍。

如果您有兴趣了解有关动画性能的更多信息,我在React Rally上就此主题进行了演讲。它深入探讨了这个主题:

根据您的浏览器和操作系统,您可能已经注意到一些较早的示例中有一些奇怪的不完善之处:

密切注意字母。请注意,它们似乎在运输过程的开始和结束时略有毛刺,好像一切都已锁定到位了吗?

发生这种情况是由于计算机的CPU和GPU之间的切换。让我解释。

当我们使用transform和opacity为元素设置动画时,浏览器有时会尝试优化此动画。与其栅格化每帧上的像素,不如将所有内容作为纹理传输到GPU。 GPU非常擅长进行此类基于纹理的转换,因此,我们获得了非常流畅,性能卓越的动画。这就是所谓的“硬件加速”。

这就是问题所在:GPU和CPU呈现的内容略有不同。当CPU将其移交给GPU时(反之亦然),您会发现事情发生了一些细微的变化。

will-change是一个属性,它使我们可以向浏览器提示我们要为选定的元素设置动画,并且应该针对这种情况进行优化。

实际上,这意味着浏览器将让GPU始终处理该元素。无需再在CPU和GPU之间进行交接,也无需再说“抢购”。

意志的改变让我们有意识地决定了哪些元素应该被硬件加速。浏览器对此有自己难以理解的逻辑,因此我宁愿不要任其发展。

在下面查看这两个动画。一种是使用margin-top完成的,因此无法通过硬件加速。注意两者之间的区别吗?

像margin-top这样的属性不能渲染次像素,这意味着它们需要四舍五入到最接近的像素,从而产生阶梯状,扭曲的效果。同时,由于GPU的抗锯齿技巧,变换可以在像素之间平滑切换。

通过将元素渲染委派给GPU,它将消耗更多的视频内存,而这种资源可能会受到限制,尤其是在低端移动设备上。

这不是以前的大事-我已经在印度颇受欢迎的预算智能手机Xiaomi Redmi 7A上进行了一些测试,而且看起来还算不错。只是将遗嘱变更广泛地应用于不会移动的元素。注意在哪里使用它。

就目前而言,我们有一个&对称的" transition —输入动画与退出动画相同:

当鼠标悬停在元素上时,它将在250ms内向上移动10个像素

一个可爱的小细节是为每个动作提供自己的过渡设置。对于悬停动画,我希望使输入动画快速而生动,而退出动画可以更加放松和昏昏欲睡:

另一个常见的例子是模态。对于模态来说,使用缓动动画输入以及使用快速缓动动画退出可能是有用的:

我相信大多数开发人员都是根据状态来考虑的:例如,您可能会看到这种情况,并说我们有一个“悬停”状态和一个默认状态。相反,如果我们从行动的角度思考呢?我们根据用户的活动进行动画,根据事件而不是状态进行思考。我们有一个鼠标输入动画和一个鼠标离开动画。

托比亚斯·阿林(Tobias Ahlin)在他的博客文章“具有动作驱动的动画的Meaningfun Motion”中展示了这个想法如何创建下一级语义上有意义的动画。

好吧,我们在精通CSS过渡方面已经走了很长一段路,但是还有两个最后的细节要讲。让我们谈谈转换延迟。

作为开发人员,您可能可以弄清楚发生这种情况的原因:下拉菜单仅在悬停时保持打开状态!当我们斜向移动鼠标以选择一个孩子时,我们的光标越界,菜单关闭。

这个问题可以用一种相当优雅的方式解决,而无需接触JS。我们可以使用过渡延迟!

过渡延迟使我们可以在短时间内保持现状。在这种情况下,当用户将鼠标移到.dropdown-wrapper外部时,在300ms内没有任何反应。如果他们的鼠标在该300ms窗口内重新输入该元素,则转换永远不会发生。

经过300毫秒后,过渡会正常开始,并且下拉菜单会在400毫秒内逐渐消失。

当元素在悬停时上下移动时,我们需要非常小心,不要意外引入“暗淡闪烁”: 警告:此GIF包含闪烁的动作,可能会导致光敏性癫痫患者癫痫发作。 您可能已经注意到此页面上某些演示的类似效果! 当鼠标位于元素边界附近时,就会发生此问题。 悬停效果使元素从鼠标下方移出,这导致其在鼠标下方掉落,这导致悬停效果再次触发……每秒多次。 我们该如何解决? 诀窍是将触发器与效果分开。 这是一个简单的示例: 我们的< button> 现在有一个新的孩子,.background。 此跨度包含所有装饰样式(背景颜色,字体等)。 当我们将鼠标悬停在普通按钮上时,它会使孩子窥视上方。 但是,该按钮是固定的。

当我在网络上看到精心制作的动画时,我会欣喜若狂。但是人与人不同,有些人的反应却截然不同:恶心和不适。

我之前写过关于尊重“减少动作的偏好”的文章,用户可以通过OS级设置进行切换,以表达对减少动作的偏好。让我们通过为请求动画的人禁用动画来在此处应用这些课程:

这个小的调整意味着动画将立即为进入系统偏好设置并切换复选框的用户解析。

作为前端开发人员,我们有一定责任确保我们的产品不会造成伤害。这是我们可以执行的快速步骤,以使我们的网站/应用程序更友好,更安全。

CSS过渡是基本的,但这并不意味着它们很容易。他们的深度令人惊讶。即使在这篇冗长的博客文章中,我也不得不删掉一些东西以使其易于管理!

Web动画比大多数开发人员意识到的重要。在这里或那里进行一次转换不会产生或破坏一种体验,但它会加在一起。总体而言,执行良好的动画可能会对整体用户体验产生令人惊讶的深远影响。

过渡可以使应用程序具有真实感。他们可以提供反馈,并以比单独复制更为公开的方式进行交流。他们可以教人们如何使用您的产品。他们可以激发喜悦。

如果您喜欢本教程,可能会很高兴知道我正在构建CSS课程! 我的课程是专门为JavaScript开发人员设计的,它是一门全面的综合课程,教您如何对CSS充满信心和无所畏惧。 它建立在与该博客相同的技术堆栈上,因此它具有相同样式的嵌入式交互式小部件,但范围甚至更广。 我的课程包括视频,迷你游戏,研讨会等。 最后,没有"沙盒模式&#34 ;,就没有互动课程是完整的! 玩所有以前的设置(以及几个新设置!),并使用此开放式小部件创建一些生成艺术作品:

2020-12-18 16:4
2020-12-7 22:47