10 个使用 CSS Transforms 的下拉菜单动画

2025-06-04

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-origintop 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 动画不透明度来分别将每个菜单项动画到视图中。0display: 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几乎与整个菜单动画完全相同,除了opacity0到 的动画之外1

@keyframes rotateX {
  0% {
    opacity: 0;
    transform: rotateX(-90deg);
  }
  50% {
    transform: rotateX(-20deg);
  }
  100% {
    opacity: 1;
    transform: rotateX(0deg);
  }
}
文章来源:https://dev.to/codypearce/10-dropdown-menu-animations-with-css-transforms-3fd6
PREV
使用 CSS 绘制并制作 Bender 的脸部动画
NEXT
使用 oh-my-zsh 的更好的 shell 使用 oh-my-zsh 的更好的 shell ===========================[ 第 1 行 ]========================== ============================[ 第 2 行 ]=========================== 更改此参数的值以显示不同的未跟踪文件图标。 更改此参数的值以显示不同的存储文件图标。 更改此参数的值以显示不同的冲突文件图标。 更改此参数的值以显示不同的暂存文件图标。 更改此参数的值以显示不同的未暂存文件图标。排版-g POWERLEVEL9K_CONTEXT_{DEFAULT,SUDO}_{CONTENT,VISUAL_IDENTIFIER}_EXPANSION=