原文: https://www.freecodecamp.org/news/how-to-build-a-dropdown-menu-with-javascript/

如果你使用互联网,你可能曾经使用过下拉菜单。它们主要有两个用途:在网络表单中收集用户的输入,以及在网络应用中实现动作/导航菜单。

下拉菜单是为类似的元素集合提供众多选项而不需要影响到应用程序的总体布局流程的最佳方式之一。除了网络应用,它们也被用于独立的软件、操作系统等。

在这篇指南中,你将学习如何使用 HTML、CSS 和 JavaScript 创建一个下拉导航菜单。

下面是你将要创建的项目的截图。在本指南的末尾,我将包括代码文件,以便你可以基于它来尝试。

dropdown-menu-with-css
下拉菜单的最终效果

现在我们已经介绍了下拉菜单的基本原理,让我们来讨论如何创建一个下拉菜单的步骤。

第 1 步 - 为下拉菜单添加标记

由于我们将在本指南中使用图标,我们需要首先导入它们。为了简单起见,我们将使用一个叫做 Boxicons 的免费库。你可以自由选择你喜欢的其他资源。

有几种方法可以在你的网站上设置 Boxicons。但最简单的方法是在你的 HTML 文件的 head 定义脚本标签,像这样:

<head>
   <link 
     href="https://unpkg.com/boxicons@2.1.4/css/boxicons.min.css" 
     rel="stylesheet"
    />
 </head>

导入图标后,创建一个 class 为 containerdiv 元素。这个元素将包含 button 和下拉菜单。

在容器内,创建一个按钮元素,将 class 和 id 设置为 btn。对于这个按钮,传入按钮文本和箭头图标。

下面是按钮的标记。

<button class="btn" id="btn">
  Dropdown
  <i class="bx bx-chevron-down" id="arrow"></i>
</button>

接下来,我们将为下拉菜单本身添加标记。在按钮标签下面,创建一个 div 元素,将 class 和 id 设置为 dropdown。在这个 div 元素中,为每个单独的下拉菜单项目创建一个 a 标签,并输入它们各自的图标和文本。

下面是标记的样子:

<div class="dropdown" id="dropdown">
  <a href="#create">
    <i class="bx bx-plus-circle"></i>
    Create New
  </a>
  <a href="#draft">
    <i class="bx bx-book"></i>
    All Drafts
  </a>
  <a href="#move">
    <i class="bx bx-folder"></i>
    Move To
  </a>
  <a href="#profile">
    <i class="bx bx-user"></i>
    Profile Settings
  </a>
  <a href="#notification">
    <i class="bx bx-bell"></i>
    Notification
  </a>
  <a href="#settings">
    <i class="bx bx-cog"></i>
    Settings
  </a>
</div>

输出是这样的:

dropdown-menu-markup
下拉菜单标记预览

它看起来还不是很好--所以让我们开始为菜单设置样式。

第 2 步 - 为下拉菜单设计样式

首先,我们将重置页面上每个元素的默认边距和填充,并在变量中存储一些值,这样我们就可以在 CSS 文件中重复使用。然后,我们将给 body 元素一些全局样式。

@import url(https://fonts.googleapis.com/css?family=Inter:100,200,300,regular,500,600,700,800,900);

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Inter", sans-serif;
  --shadow: rgba(0, 0, 0, 0.05) 0px 6px 10px 0px,
    rgba(0, 0, 0, 0.1) 0px 0px 0px 1px;
  --color: #166e67;
  --gap: 0.5rem;
  --radius: 5px;
}

body {
  margin: 2rem;
  background-color: #b3e6f4;
  font-size: 0.9rem;
  color: black;
}

下一步是为按钮和下拉容器本身设计样式。为了加快进度,我将只解释样式的重要部分。

复制下面的标记并粘贴到你的 CSS 文件中。

.btn {
  background-color: white;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  column-gap: var(--gap);
  padding: 0.6rem;
  cursor: pointer;
  border-radius: var(--radius);
  border: none;
  box-shadow: var(--shadow);
  position: relative;
}

.bx {
  font-size: 1.1rem;
}

.dropdown {
  position: absolute;
  width: 250px;
  box-shadow: var(--shadow);
  border-radius: var(--radius);
  margin-top: 0.3rem;
  background: white;
}

.dropdown a {
  display: flex;
  align-items: center;
  column-gap: var(--gap);
  padding: 0.8rem 1rem;
  text-decoration: none;
  color: black;
}

.dropdown a:hover {
  background-color: var(--color);
  color: white;
}

由于下拉菜单通常被放置在元素之上,所以按钮被定位为相对位置,而下拉菜单被定位为绝对位置。这保证了两个元素会相互靠近,而下拉菜单会被放在元素上方。这样,当切换时,不会影响页面的内容。

输出如下:

image-1
下拉菜单样式

现在,下拉菜单已经被设置了样式,我们希望它只在按钮被点击后出现,而不是立即出现。为了隐藏它,我们将使用 CSS。

在我之前写的一篇关于如何用 JavaScript 构建模态框的文章中,我们用 display: none 将模态元素从视口中初步隐藏起来。但根据 MDN 文档,使用这个属性的缺点是不能给它添加动画。

所以,在本指南中,我们将采用不同的方法来隐藏下拉菜单。这涉及到将 visibilityopacity 属性结合在一起以获得所需的结果。这种方法是 GitHub 实现其下拉菜单的方式。

github-dropdown-menu
GitHub 上的下拉菜单

在我们之前创建的下拉菜单类中,添加一个 visibility 属性,给它一个值 hidden,并将 opacity 设置为 0,这样做将从页面中隐藏下拉菜单。

为了显示模态框,我们将创建一个单独的类,叫做 show。这个类将包含 visibility 属性,其值为 visibleopacity1。我们可以用 JavaScript 将这个类注入模态框中。

下面是代码:

.dropdown {
  position: absolute;
  width: 250px;
  box-shadow: var(--shadow);
  border-radius: var(--radius);
  margin-top: 0.3rem;
  background: white;
  transition: all 0.1s cubic-bezier(0.16, 1, 0.5, 1);
    
  transform: translateY(0.5rem);
  visibility: hidden;
  opacity: 0;
}

.show {
  transform: translateY(0rem);
  visibility: visible;
  opacity: 1;
}

.arrow {
  transform: rotate(180deg);
  transition: 0.2s ease;
}

除了隐藏模态元素的样式之外,我们还添加了另一个类,当点击下拉按钮时,旋转箭头图标。

第 3 步 - 添加下拉功能

首先,让我们将各元素存储到变量中,以便它们可以重复使用。

const dropdownBtn = document.getElementById("btn");
const dropdownMenu = document.getElementById("dropdown");
const toggleArrow = document.getElementById("arrow");

下一步是创建一个函数来切换下拉元素上的 show 类,并在点击按钮时旋转下拉箭头。我们将这个函数命名为 toggleDropdown

const toggleDropdown = function () {
  dropdownMenu.classList.toggle("show");
  toggleArrow.classList.toggle("arrow");
};

然后我们可以使用 addEventListener 方法在下拉按钮上调用这个函数。因此,无论何时点击按钮,它都会触发这个函数,控制显示和隐藏下拉菜单。

dropdownBtn.addEventListener("click", function (e) {
  e.stopPropagation();
  toggleDropdown();
});

如果你注意到,我们在下拉函数里面添加了一个 stopPropagation() 方法。这可以防止按钮元素的函数向下传递到父元素,从而阻止了函数的两次运行。你会在下一节了解更多关于这个的内容。

下面是输出结果:

toggle-dropdown-menu-
下拉菜单切换

如何在 DOM 元素被点击时关闭下拉菜单

下拉菜单通常以四种不同的方式关闭:

  • 通过点击激活它的按钮
  • 通过点击它的任何一个子元素
  • 通过点击菜单外(在 body 上)
  • 通过点击 Escape 或向下箭头键

但在本指南中,让我们集中讨论前三种方式。

首先,我们将使用 document.documentElement 选择根元素 <html>。和之前一样,我们将在里面传入 toggleDropdown() 函数。

但是这一次,我们要定义一个条件,检查下拉菜单是否包含 show 类。只有当它包含时,我们才要启动关闭函数。

document.documentElement.addEventListener("click", function () {
  if (dropdownMenu.classList.contains("show")) {
    toggleDropdown();
  }
});

这是最终的结果:

close-dropdown-when-dom-element-is-clicked
当 DOM 元素被点击时关闭下拉菜单

这就是你如何用 JavaScript 创建一个下拉菜单。下面是测试这个下拉菜单的 CodePen 代码文件

See the Pen Dropdown menu by Eke (@evavic44) on CodePen.

总结

我真诚地希望你觉得这篇文章有趣或有用。如果你喜欢这篇文章,请与你的朋友分享或订阅我的博客,这样你就不会错过任何未来的文章。谢谢你阅读本文。

GitHub | Twitter | 博客 | 作品集