原文: How to Build a Dropdown Menu with JavaScript

インターネットを使うかたなら、おそらくドロップダウンメニューを使ったことがあるでしょう。ドロップダウンメニューは主に 2 つの目的で使用されます。1 つはウェブフォームでユーザーの入力を収集するため、もう 1 つはウェブアプリケーションにアクションやナビゲーションメニューを実装するためです。

ドロップダウンは、似たようなの要素の集まりに対して多数のオプションを提供する最良の方法の 1 つです。これにより、アプリケーションの一般的なレイアウトの流れを崩さずに多くの選択肢を提供することができます。ウェブアプリ以外にも、ドロップダウンメニューはスタンドアロンのソフトウェアやオペレーティングシステムなどでも使用されています。

このガイドでは、HTML、CSS、JavaScript を使用してドロップダウンナビゲーションメニューを作成する方法を学びます。

以下は、これから作成するもののスクリーンショットです。このガイドの最後に、CodePen ファイルを提供しているので、それを使って実際に試してみることができます。

dropdown-menu-with-css
ドロップダウンメニューの最終成果物

ドロップダウンメニューの基礎についての説明を終えたので、次はその作成手順について説明します。

ステップ 1 – ドロップダウンのマークアップを追加する

このガイドではアイコンを使用するため、まず初めにアイコンをインポートしなければなりません。その分かりやすさから、Boxicons という無料のライブラリを使用します。他にもあるので、ぜひお好きなライブラリを使ってみて下さい。

Boxicons を設定する方法はいくつかありますが、最も簡単な方法は、次のように HTML ファイルの head で script タグを定義することです。

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

アイコンをインポートした後、クラス名が containerdiv 要素を作成します。この要素内に、ボタンとドロップダウンメニューを入れていきます。

コンテナ内でボタン要素を作成し、それに btn というクラスと ID を与えます。そのボタンに、テキストと矢印アイコンを渡します。

ボタンのマークアップは以下のとおりです。

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

次に、ドロップダウンメニュー自体のマークアップを追加します。button タグの下に div 要素を作成し、それに dropdown というクラスと ID を与えます。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;
}

ドロップダウンメニューは通常、要素の上に重なるように表示されるため、ボタンを相対的 (relative) に、ドロップダウンメニューを絶対的 (absolute) に配置しています。これにより、両方の要素が近くに配置され、ドロップダウンメニューが他の要素の上に表示されることが保証されます。こうすることで、切り替え時にページのフローに影響を与えなくなります。

出力は以下のようになります。

dropdown-menu-with-css--1-
ドロップダウンメニューのスタイリング

ドロップダウンのスタイルが設定されたので、即座に表示されるのではなく、ボタンがクリックされたときにのみドロップダウンが表示されるようにしたいと思います。非表示にするには CSS を使用します。

以前 JavaScript でモーダルを作成する方法という記事では、最初にビューポートからモーダル要素を非表示にするために、display: none を使用しました。しかし、MDN Docs によると、このプロパティを利用する場合の欠点は、アニメーション化できないことです。

したがってこのガイドでは、別の方法を用いてドロップダウンメニューを非表示にしたいと思います。これには、visibilityopacity のプロパティを組み合わせることで、達成することができます。そしてこの方法は、GitHub がドロップダウンメニューを実装している方法です。

github-dropdown-menu
GitHub のドロップダウンメニュー

前に作成したドロップダウンクラス内に、visibility プロパティを追加し、値を hidden に設定したら、不透明度を 0 に設定します。そうすることで、ページからドロップダウンメニューが非表示になります。

ドロップダウンメニューを表示するために、show という別のクラスを作成します。このクラスは、visible の値と不透明度 1 の visibility プロパティを保持します。そして、後ほど 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() メソッドを追加しました。これにより、ボタン要素の機能が親要素に伝達されるのを防ぎ、関数が 2 回実行されるのを防ぐことができます。次のセクションでこれについて詳しく説明します。

出力は以下のようになります。

toggle-dropdown-menu-
ドロップダウンメニューの切り替え

DOM 要素をクリックしたときにドロップダウンメニューを閉じる方法

ドロップダウンメニューは通常、次の 4 つの異なる方法で閉じられます。

  • ドロップダウンメニューを有効にするボタンをクリックすること
  • 子要素のいずれかをクリックすること
  • メニューの外側 (ボディ部分) をクリックすること
  • Esc キーまたは下矢印キーを押すこと

ただし、このガイドでは、最初の 3 つに焦点を当てましょう。

まず、document.documentElement を使用してルート要素 <html> を選択します。そうしたら、先ほどと同様に toggleDropdown() 関数を渡します。

しかし、今回はドロップダウンメニューが show というクラスを持っているかどうかをチェックする条件を設定したいと思います。show というクラスを持っている場合にのみ、ドロップダウンメニューを閉じる関数を実行したいからです。

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

その結果が、最終的にこのようになります。

close-dropdown-when-dom-element-is-clicked
DOM 要素をクリックするとドロップダウンが閉じる

これが JavaScript でドロップダウンメニューを作成する方法です。以下は、このドロップダウンメニューをテストするための CodePen ファイルです。

まとめ

この投稿が興味深かったり、役に立ったと感じていただければ幸いです。今後の投稿を見逃さないよう、お友達と共有するか、私のブログを読者登録してみてください。読んでくださりありがとうございます。

GitHub | Twitter | Blog | Portfolio