10 个使用 CSS Transforms 的下拉菜单动画
本文最初发表于codinhood.com
下拉菜单允许用户查看有关特定主题的更多信息,而不会在页面上显示过多的信息。大多数下拉菜单动画遵循以下两种模式之一:将整个菜单作为一个组进行动画处理,或单独为菜单中的每个项目进行动画处理。CSS 变换使我们能够以出色的性能为这两种模式制作动画,因为 CSS 变换会影响浏览器关键渲染路径中的“合成”步骤,而不是“绘制”、“布局”或“样式”步骤。以下是五个使用 CSS 变换对整个菜单和每个项目分别进行动画处理的动画。CSS 语法是Stylus,类似于SASS。
虽然动画可以添加一些有趣的视觉效果,但请记住这些示例略微夸张,以使动画的机制更加明显。
动画整个下拉菜单
所有菜单的结构都是相同的:dropdown
是菜单标题和隐藏菜单的容器。dropdown_menu
是实际菜单本身,默认情况下是隐藏的。
<li class="dropdown dropdown-6">
Scale Down
<ul class="dropdown_menu dropdown_menu--animated dropdown_menu-6">
<li class="dropdown_item-1">Item 1</li>
<li class="dropdown_item-2">Item 2</li>
<li class="dropdown_item-3">Item 3</li>
<li class="dropdown_item-4">Item 4</li>
<li class="dropdown_item-5">Item 5</li>
</ul>
</li>
仅当鼠标悬停在整个下拉菜单(标题和按钮)上时才会显示dropdown_menu
。这将在悬停时显示下拉菜单,且不带任何动画。
.dropdown_menu
position: absolute
top: 100%
left: 0
width: 100%
perspective: 1000px
display: none
.dropdown:hover .dropdown_menu--animated
display: block
要为菜单添加动画效果,我们需要将animation
属性添加到dropdown_menu
。该animation-name
属性应设置为我们为规则指定的名称@keyframes
,在本例中为growDown
。该animation-fill-mode
属性定义了动画结束时应应用的样式。在本例中,我们将菜单从关闭状态动画到打开状态。这意味着我们希望下拉菜单保留最终动画状态的样式, 值forwards
允许我们这样做。
.dropdown_menu-6
animation: growDown 300ms ease-in-out forwards
我们需要考虑的最后一个属性是transform-origin,它定义了动画的应用位置。对于我们的动画来说,此属性定义了菜单的物理起始位置。默认设置transform-origin
将从“菜单中心”而不是按钮缩放菜单。例如,roateX
使用默认值对 transform 属性进行动画处理将如下所示transform-origin
。
更改transform-origin
为top center
将使动画从按钮旋转。
.dropdown_menu-6
animation: growDown 300ms ease-in-out forwards
transform-origin: top center
我们可以从21 个变换函数中选择任意一个,使用@keyframes规则为菜单添加动画效果。唯一需要遵循的规则是,动画的最终状态,即100%
属性,必须是菜单打开时的正常状态。例如,如果我们scaleY
为菜单的 制作动画,我们需要确保scaleY
设置为1
,这样动画结束时菜单才能正常显示。
80%
你会注意到,每个动画都会在或左右“超越”预期的结束状态,70%
然后在 处返回到结束状态100%
。这是动画中常见的技巧,用于营造动量或“弹跳”的视觉效果,使其更加自然。下面展示了两个示例,更多示例请查看上方的 Codepen。
@keyframes growDown {
0% {
transform: scaleY(0)
}
80% {
transform: scaleY(1.1)
}
100% {
transform: scaleY(1)
}
}
@keyframes rotateMenu {
0% {
transform: rotateX(-90deg)
}
70% {
transform: rotateX(20deg)
}
100% {
transform: rotateX(0deg)
}
}
为每个菜单项添加动画
HTML 结构与整个菜单的动画相同。但是,除了设置 之外,每个菜单项还需要设置opacity
为。我们这样做是因为我们不希望所有菜单项都立即可见,就像我们为整个菜单设置动画时那样。相反,我们将通过使用 transform 动画不透明度来分别将每个菜单项动画到视图中。0
display: none
.dropdown_menu li
display: none
color: white
background-color: #34495e
padding: 10px 20px
font-size: 16px
opacity: 0
&:hover
background-color: #2980b9
.dropdown:hover .dropdown_menu li
display: block
为整个菜单添加动画意味着我们只需为每个菜单添加一个动画,但为每个菜单项单独添加动画则意味着我们需要animation
为每个菜单项添加单独的属性。幸运的是,所有菜单项都共享相同的@keyframe
规则、相同的持续时间、相同的计时函数、相同的animation-fill-mode
和相同的transform-origin
属性。唯一需要不同的属性是animation-delay,用于错开每个菜单项的动画。
我们可以为每个下拉菜单项手动编写一个 CSS 选择器,并设置不同的动画延迟,或者利用 Stylus 的for 循环来迭代每个下拉菜单项并自动生成这些选择器。最终结果是一样的,所以让我们使用for
循环来简化操作。
每个下拉菜单有五个菜单项,要迭代五次,我们可以使用以下语法:for num in (1..5)
。每个dropdown_item
菜单项都有一个带序列号的类:dropdown_item-1
,,dropdown_item-2
等等。因此,我们可以使用num
变量和选择器插值来选择每个菜单项:.dropdown_item-{num}
。最后,我们可以使用num
变量将每个菜单项延迟均匀的量。如果动画持续时间为,并且总共有 5 个菜单项,那么我们可以按增量300ms
延迟每个菜单项: 。将所有这些放在一起得到以下内容:60ms
(num * 60ms)
.dropdown_menu-2
for num in (1..5)
.dropdown_item-{num}
animation: rotateX 300ms (num * 60ms) ease-in-out forwards
transform-origin: top center
规则@keyframe
几乎与整个菜单动画完全相同,除了opacity
从0
到 的动画之外1
。
@keyframes rotateX {
0% {
opacity: 0;
transform: rotateX(-90deg);
}
50% {
transform: rotateX(-20deg);
}
100% {
opacity: 1;
transform: rotateX(0deg);
}
}