萨利赫·穆巴沙尔撰写✏️
直到最近,只有有限数量的 CSS 属性可以进行动画处理。例如,要创建淡入或淡出效果,通常会使用 opacity 属性而不是 display 属性,因为后者无法设置动画。然而,问题是,虽然该元素在视觉上变得隐藏,但它仍然存在于页面上。
最近,Chrome 推出了新功能来解决此问题并使开发过程变得更加简单。在本文中,我们将比较显示和大小属性动画的传统方法与这些新功能。
有可能,您必须在某些时候使用 CSS 在某些元素上创建淡入/淡出效果。首选方法是将动画或过渡应用到元素的不透明度。但将不透明度设置为零实际上并不会删除该元素 - 它只是使其不可见。大多数时候,这就足够了。
但是假设您有一个待办事项列表,用户可以在其中删除项目。如果要创建退出动画以使项目淡出,通常会使用不透明度。但如果列表需要调整其高度,您还需要将显示设置为无。这里的问题是,虽然该项目在视觉上消失了,但它仍然占用 DOM 中的空间,并扰乱布局和用户交互等内容。
这是两种方法的并排比较:一种仅使用不透明度,另一种将不透明度与显示相结合。您可以尝试下面的示例来查看差异:
查看 CodePen 上 Saleh-Mubahar (@saleh-mubahar) 的 Pen Simple Todo 应用程序比较。
请注意,将显示与不透明度结合使用时布局如何变化,而单独使用不透明度会在列表中留下间隙。虽然第二种方法(不透明显示)解决了布局问题,但它会干扰平滑的淡出效果,因为在淡入淡出完成之前应用了 display: none。这会导致突然消失而不是逐渐褪色。
例如,不透明度属性可以从 0 平滑过渡到 1。但是,显示属性无法进行动画处理,因为它没有数字范围 - 它的状态是二进制的,例如无、块或其他值。由于没有中间值,CSS 无法为显示设置动画。
同样,开发人员在尝试对元素的固有大小(例如 height: auto)进行动画处理时经常面临挑战。这通常用于可折叠部分(如手风琴)上的过渡,其中高度在关闭时从 0px 开始,并在打开时扩展以适应内容。虽然尺寸属性(如高度)通常可以进行动画处理(因为它们具有数字起始值和结束值),但自动设置动画或从自动设置动画会产生问题。浏览器无法计算0px和auto之间的步长;因此必须使用复杂的解决方法。
有多种方法可以解决动画显示和元素大小的挑战。在本节中,我们将讨论使用 CSS 和 JavaScript 的最流行的解决方案。
有几种方法可以解决使用 CSS 无法设置动画的显示属性的问题。最可靠的方法是使用不透明度以及尺寸属性(例如高度或宽度)。在这种情况下,size 属性用于有效地从 DOM 中删除元素。这可以使用转换延迟属性来完成。基本上,我们为尺寸过渡添加延迟,该延迟等于为不透明度过渡设置的时间。一旦元素淡出,其大小立即设置为零,有效地将其从布局中删除,就好像未应用 display: none 一样。
再次使用待办事项列表作为示例,实现看起来有点像这样:
li { height: 50px; /* any measurable value, not "auto" */ opacity: 1; transition: height 0ms 0ms, opacity 400ms 0ms; } .fade-out { overflow: hidden; /* Hide the element content, while height = 0 */ height: 0; opacity: 0; padding: 0; transition: height 0ms 400ms, padding 0ms 400ms, opacity 400ms 0ms; }
这里的技巧是,一旦不透明度褪色到 0,延迟后将高度和填充设置为 0。不透明度的延迟和长度需要相同 - 在本例中为 400 毫秒。 height: 0 确保列表项不与布局交互。如前所述,height: auto 根据内容动态调整;因此,它不能被动画化。因此,您需要确保元素具有特定的固定高度,以使动画正常工作。
将可见性设置为隐藏是另一种常用的方法。但是,这不会从 DOM 中删除该元素,它仍然会像平常一样影响布局,即它会影响周围元素的位置。
将元素动画化为其固有尺寸(或高度:自动)的最常见 CSS 解决方案是使用 max-height 而不是 height。这不是最简洁的实现,但它可以完成工作。基本上,您将 max-height 设置为大于元素所能获得的值。这样,它就可以模仿平滑过渡,类似于固定高度的动画:
.collapsible { max-height: 0; overflow: hidden; transition: max-height 0.4s ease; } .collapsible.open { max-height: 500px; }
这种方法最明显的缺点是您必须确保最大高度始终大于元素内的实际内容。另一个问题是,除非内容高度与最大高度值完全匹配,否则过渡时间可能会感觉不准确。
假设您的内容高 400 像素,但您将最大高度设置为 1000 像素。从技术上讲,动画将在整个持续时间内持续(假设两秒)。但从视觉上看,元素一旦达到内容的实际高度(400px)就会停止增长,而 max-height 不断过渡到 1000px。因此,在这种情况下,过渡持续时间将比您指定的时间短。
上面讨论的所有 CSS 解决方案都非常复杂,并且可能会导致不可预测的结果。直到最近,实现这一目标的最可靠方法还是通过 JavaScript。
要在不透明度转换后应用不显示,我们可以使用 setInterval 或 setTimeout 函数来添加与不透明度转换持续时间匹配的延迟。在此延迟之后,您可以将显示设置为无。这是一个例子:
li { height: 50px; /* any measurable value, not "auto" */ opacity: 1; transition: height 0ms 0ms, opacity 400ms 0ms; } .fade-out { overflow: hidden; /* Hide the element content, while height = 0 */ height: 0; opacity: 0; padding: 0; transition: height 0ms 400ms, padding 0ms 400ms, opacity 400ms 0ms; }
在此代码中,单击按钮后,元素会在一秒钟内淡出,然后其显示立即设置为无 - 实质上是将其从布局中删除。
类似地,为了对内在尺寸进行动画处理,我们可以在 JavaScript 中计算元素的高度,并使用该值作为高度的端点。这种方法更加可靠和精确。但是,请记住,我们仍在高度属性上设置动画。
这里明显的好处是,您可以根据元素的实际内容动态设置高度,确保过渡与真实高度匹配,而不是用 max-height 进行猜测。
具体操作方法如下:
.collapsible { max-height: 0; overflow: hidden; transition: max-height 0.4s ease; } .collapsible.open { max-height: 500px; }
在此示例中,我们扩展了一个以 0 高度开始的部分。我们使用scrollHeight 来获取内容的完整高度,并将其用作过渡的端点。转换完成后,我们将高度切换为自动,这允许浏览器根据容器的内容自动调整容器的高度。此步骤是可选的,但如果您希望容器内的内容随着时间的推移而变化,它会很有用。
现在让我们看看最近发布或即将发布到浏览器的 CSS 新功能。这些新工具消除了我们之前讨论的场景中对 JavaScript 的需求,并帮助您编写更清晰、更短的 CSS。
@keyframes at 规则允许您通过控制动画序列中的中间步骤来创建动画。最新更新允许您在关键帧时间轴内对显示和内容可见性属性进行动画处理。
我们并没有完全在 display none 和 block 之间进行插值(因为这是不可能的)。相反,我们等待所有其他效果完成,然后切换显示状态。这与我们对 JavaScript 所做的类似 - 在应用 display: none 之前等待转换完成 - 但现在使用 CSS 更容易。
Chrome 开发博客有一个非常酷的演示,让事情变得清晰:
观看笔淡出卡片 - CodePen 上 web.dev (@web-dot-dev) 的动画。
首先,在 250 毫秒内将不透明度设置为 0。此序列完成后,显示立即设置为无:
li { height: 50px; /* any measurable value, not "auto" */ opacity: 1; transition: height 0ms 0ms, opacity 400ms 0ms; } .fade-out { overflow: hidden; /* Hide the element content, while height = 0 */ height: 0; opacity: 0; padding: 0; transition: height 0ms 400ms, padding 0ms 400ms, opacity 400ms 0ms; }
这里最大的好处是涉及显示属性的更复杂的动画,直到最近使用 CSS(或 JavaScript)实现起来都非常困难,现在可以相对轻松地创建。
现在还可以使用新的 [transition-behavior](https://developer.mozilla.org/en-US/docs/Web/CSS/transition-behavior) 属性通过过渡来创建淡出效果。这使您可以将过渡应用于具有离散动画行为的属性,例如显示。通过使用allow-discrete,您可以为显示属性设置动画。这是一个简单的例子:
.collapsible { max-height: 0; overflow: hidden; transition: max-height 0.4s ease; } .collapsible.open { max-height: 500px; }
我们在本文中广泛讨论了淡出效果。但相反的情况又如何呢?进入动画很棘手,通常只能通过 JavaScript 实现。新的 @starting-style at-rule 让事情变得更加容易。
顾名思义,我们可以使用它来将样式应用于元素,浏览器可以在元素在页面上可见之前查找该样式。我们可以在这里设置进入动画的初始状态。元素渲染后,它会转换回默认状态。
这是一个基本示例:
document.getElementById("fadeButton").addEventListener("click", function () { const element = document.getElementById("myElement"); element.style.opacity = "0"; setTimeout(() => { element.style.display = "none"; }, 1000); // Match this value with the duration in CSS });
一旦 DOM 加载,卡片就会淡入。您可以将@starting-style用于各种进入动画。这是 Chrome 开发团队的另一个很棒的示例:
_查看 CodePen 上 web.dev (@web-dot-dev) 的笔项目转换。
_
最近在 Chrome 129 中引入了类似于 calc() 的 calc-size 函数。简单来说,它允许安全可靠地对内在大小执行数学运算。目前支持auto、min-content、max-content、fit-content 四个关键字的操作。
这对于将元素动画化到其固有尺寸或改变其固有尺寸特别有用。 calc-size 允许将当前在 CSS 中指定的任何高度动画化为零或到/从一个小的固定值。这是一个将可折叠部分从 height: 0 扩展到 auto:
的简单示例
li { height: 50px; /* any measurable value, not "auto" */ opacity: 1; transition: height 0ms 0ms, opacity 400ms 0ms; } .fade-out { overflow: hidden; /* Hide the element content, while height = 0 */ height: 0; opacity: 0; padding: 0; transition: height 0ms 400ms, padding 0ms 400ms, opacity 400ms 0ms; }
这些功能大部分主要是为了增强动画而不是必需的 DOM 组件,但由于它们相对较新,因此仍然值得检查浏览器兼容性:
在本文中,我们探讨了开发人员在对 CSS 属性(如显示和元素大小)进行动画处理时面临的挑战。传统方法需要使用 CSS 和 JavaScript 进行复杂的解决方法,才能为无法直接设置动画的属性实现动画。
新功能,例如使用关键帧进行动画显示、calc-size() 函数和过渡行为属性,使这些动画更容易实现。这些函数消除了对 JavaScript 的需求,从而允许更简单的 CSS 动画。
随着 Web 前端变得越来越复杂,资源贪婪的功能对浏览器的要求越来越高。如果您有兴趣监控和跟踪生产中所有用户的客户端 CPU 使用情况、内存使用情况等,请尝试 LogRocket。
LogRocket 就像网络和移动应用程序的 DVR,记录网络应用程序、移动应用程序或网站中发生的所有情况。您无需猜测问题发生的原因,而是可以汇总和报告关键前端性能指标、重放用户会话以及应用程序状态、记录网络请求并自动显示所有错误。
现代化调试 Web 和移动应用程序的方式 - 开始免费监控。
以上是使用显示和大小属性简化 CSS 动画的详细内容。更多信息请关注PHP中文网其他相关文章!