掌管前端过渡动画之神——transition👀

963 阅读4分钟

在现代网页设计中,用户体验的流畅性至关重要,CSS的transition属性正是实现这一目标的关键工具之一。它能够将网页元素的变换过程变得平滑而自然,避免元素样式瞬间变换、僵硬动画带来的糟糕用户体验。本文将深入探讨transition属性的工作原理、应用场景以及如何通过它来提升网页的交互体验。

基础知识

首先我们通过一个简单的宽度及颜色过渡的例子,了解transition的功能和相关基础知识。

  • 不设置transition时:
  • 设置transition后:
<div></div>
div {
    width: 150px;
    height: 50px;
    transition: all 1s linear 0s;
    background: red;
}
div:hover {
    width: 250px;
    background: blue;
}

transition属性文档中详细介绍了其含义:

transition CSS 属性是 transition-property、transition-duration、transition-timing-function 和 transition-delay 的一个简写属性。

  • transition-property 指定应用过渡属性的名称。
  • transition-duration 以秒或毫秒为单位指定过渡动画所需的时间。默认值为 0s,表示不出现过渡动画。
  • transition-timing-function 这个函数会建立一条加速度曲线,在整个 transition 变化过程中,变化速度可以不断改变。
  • transition-delay 规定了在过渡效果开始作用之前需要等待的时间。

💡不是所有属性都支持过渡,动画性 CSS 属性文档中对此有做解释。

过渡与用户体验

以笔者最近开发的数据看板为例,如果不增加过渡动画,看板的展开与折叠将会非常突兀: 添加过渡后: 这里笔者为按钮的悬浮置灰和折叠面板的高度都添加了过渡动画,面板会有一个明显的收起动作,而不是瞬间消失。 眼尖的读者可能会发现,面板的收起非常丝滑,但是展开动画比收起动画快了很多,下面笔者会解释原因。

使用技巧与注意事项

过渡属性需要有确定的值

笔者一开始像下面这样,在折叠状态下控制固定高度,展开后自适应高度,但实际上过渡动画没有触发,还是瞬间展开折叠了。

<div class="data-panel" :style="{height: !expandPanel ? '344px' : 'fit-content'}">
.data-panel {
  ...
  transition: max-height 0.3s ease
}

原因: CSS transtion 需要确保元素的初始和目标高度是明确的数值。 那么对于这种展开后高度不确定的折叠面板,就没有办法添加展开过渡动画了吗?非也,max-height可以解决这个问题:

<div class="data-panel" :style="{maxHeight: !expandPanel ? '344px' : '1400px'}">

只要我们将max-height的目标值设置为肯定比展开后的高度要高的一个值,就可以实现上面动图中的效果。 但是为什么会出现展开动画比收起动画快了很多的现象呢?因为这个 0.3s 本身是 344px → 1400px 的动画时间,但实际展开后如果只有 700px,那么动画实际执行的时间就只有 0.15s了。 如果不能接受这个瑕疵,实际使用中可以考虑根据数据手动计算展开后的高度,或者采用其他实现方式。

更多使用场景

鼠标悬浮菜单延迟关闭

在一些网站我们经常会遇到这种菜单,尤其是顶部导航栏上,很容易发生一种尴尬的场景:鼠标从按钮移动到菜单的过程中不小心超出了按钮和菜单的范围,菜单消失了,用户又要重新执行该操作。 假如我们采用如下方式控制菜单弹窗展示:

<div class="dropdown">
    <button class="dropbtn">菜单</button>
    <div class="dropdown-content">
        <a href="#">链接 1</a>
        <a href="#">链接 2</a>
        <a href="#">链接 3</a>
    </div>
</div>
/* 省略其他样式 */

...
.dropdown-content {
    display: none;
    ...
}

.dropdown:hover .dropdown-content {
    display: block;
}

diplay 属性是无法控制过渡时间的,如此一来只能通过 js 来控制菜单的展示时间。但我们可以换一种思路:

/* 省略其他样式 */

...
.dropdown-content {
    transition: opacity 0.3s;
    transition-delay: 1s;
    ...
}

.dropdown:hover .dropdown-content {
    opacity: 1;
    transition-delay: 0s;
}

这样当鼠标悬浮触发 hover 状态时,菜单列表会瞬间打开;而当鼠标移出菜单和按钮范围时,菜单会延迟 1s 再消失。