Create a Reusable Dropdown Component with JavaScript

In this tutorial, we’ll create a reusable, custom dropdown component, using vanilla JavaScript.

A what? One strategy to reduce a menu or navigation footprint is to place additional links inside a dropdown component. The idea is that users click to reveal more options, thus giving them more ways to navigate web pages, whilst keeping the UI clean.

For this tutorial, I’ll assume we’re building a component for a marketing agency website.

What We Are Building

Here’s our flexible dropdown navigation. Click the items with an arrow to revela the submenus:

How to Build a Dropdown Component With JavaScript

Alright, let’s get stuck in! As usual, we’ll begin with the HTML markup for our srtucture, then we’ll add some styles with CSS, and finally we’ll add the behavior with vanilla JavaScript.

HTML Structure

First, the HTML structure. We will use an unordered list with list items and links.

1
<nav role="primary navigation">
2
  <a href="#">Home</a>
3
  <div class="dropdown">
4
    <a href="#" class="dropdown-action">
5
        Services
6
        <svg class="dropdown-icon" xmlns="https://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><title>chevron-down</title><g fill="none"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.25 10.75L12 14.25l-3.25-3.5"></path></g></svg>
7
    </a>
8
    <ul class="dropdown-menu">
9
      <li><a href="#">SEO</a></li>
10
      <li><a href="#">Content Strategy</a></li>
11
      <li><a href="#">Copywriting</a></li>
12
      <li><a href="#">Storytelling</a></li>
13
    </ul>
14
  </div>
15
  <a href="#">About</a>
16
  <a href="#">Contact</a>
17
  <div class="dropdown">
18
    <a href="#" class="dropdown-action">
19
        Account
20
        <svg class="dropdown-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><title>chevron-down</title><g fill="none"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.25 10.75L12 14.25l-3.25-3.5"></path></g></svg>
21
    </a>
22
    <ul class="dropdown-menu">
23
      <li><a href="#">Login</a></li>
24
      <li><a href="#">Sign up</a></li>
25
    </ul>
26
  </div>
27
</nav>

Note the class names on the parent anchor link .dropdown-action and the unordered list .dropdown-menu. These class naming conventions are more generic, so we can reuse the CSS and JavaScript as often as we wish on the website.

Adding Some Styles With CSS

Let’s give the dropdown list some aesthetic treatments with CSS.

Remember that a core foundation of a dropdown is appropriately hiding and showing the list on demand. I’ll design the dropdown list with that in mind.

1
nav {
2
  width: 1020px;
3
  display: flex;
4
  align-items: center;
5
  margin: 20px auto;
6
  padding-bottom: 10px;
7
  border-bottom: 1px solid #ddd;
8
}
9

10
nav a {
11
  padding: 10px 16px;
12
  border-radius: 4px;
13
  display: inline-block;
14
  color: #334155;
15
  text-decoration: none;
16
}
17

18
nav a:hover {
19
  color: #0ea5e9;
20
  background-color: #f0f9ff;
21
}
22

23
.dropdown {
24
  position: relative;
25
}
26

27
.dropdown-action {
28
  display: flex;
29
  align-items: center;
30
  padding-right: 10px;
31
}
32

33
.dropdown-icon {
34
  stroke: currentColor;
35
}
36

37
.dropdown-menu {
38
  display: none;
39
  list-style: none;
40
  margin: 0;
41
  padding: 10px 0;
42
  border: 1px solid #cbd5e1;
43
  border-radius: 6px;
44
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
45
  position: absolute;
46
  top: 40px;
47
  left: 5px;
48
  min-width: 180px;
49
  background: white;
50
}
51

52
.dropdown-menu.active {
53
  display: block;
54
}
55

56
.dropdown-menu a {
57
  display: block;
58
}

Adding Interactivity with JavaScript

To make sure we can reuse the dropdown component over and over, I’ll write the JavaScript in a way that will account for any dropdown components on a given page. This means all we need to do is include the script for it to work across many dropdown components assuming the HTML and CSS match our previous work.

1
class Dropdown {
2

3
  constructor() {
4
    this.dropdowns = document.querySelectorAll('.dropdown .dropdown-menu')
5
    if (this. dropdowns.length) {
6
      this.initialize();
7
    }
8
  }
9

10

11
 initialize() {
12
    document.addEventListener('click', (e) => {
13
      if (e.target.classList.contains('dropdown-action')) {
14
        this.hideOtherDropdowns(e.target);
15
        this.handleClick(e.target);
16
      } else {
17
        this.hideOtherDropdowns(null);
18
      }
19
    });
20
  }
21

22
  handleClick(dropdownAction) {
23
    this. dropdowns.forEach(dropdown => {
24
      if (dropdown.parentElement.contains(dropdownAction)) {
25
        dropdown.classList.add('active');
26
      } else {
27
        dropdown.classList.remove('active');
28
      }
29
    })
30
  }
31

32
  hideOtherDropdowns(dropdownAction) {
33

34
    this.dropdowns.forEach((dropdown) => {
35
      if (!dropdown.parentElement.contains(dropdownAction)) {
36
        dropdown.classList.remove('active');
37
      }
38
    });
39
  }
40

41
}
42

43
document.addEventListener('DOMContentLoaded', () => new Dropdown);

Using modern ES6 syntax, I created a new Dropdown class to wrap logic for reuse on a given page. We initialize it at the very in using the following line.

1
document.addEventListener('DOMContentLoaded', () => new Dropdown);

As long as the script is included in a given page, this code is all you need to make the component come alive. We can wait for the DOM content to be loaded before initializing the Dropdown class for better results.

Our Functions (in More Detail)

Let’s break apart each function and dive deeper into what is happening.

The Constructor Method

1
constructor() {
2
  this.dropdowns = document.querySelectorAll('.dropdown .dropdown-menu')
3
  if (this. dropdowns.length) {
4
    this.initialize();
5
  }
6
}

The constructor method is used to initialize the object or class. A constructor enables you to provide any custom initialization before other methods can be called.

Here I added a querySelectorAll method that queries for all dropdown menus on a given page. We’ll loop through those in the coming functions.

Additionally, I added some conditional logic to check that dropdowns exist on a page before calling the initialize() function that is part of the class.

The initialize() Function

1
initialize() {
2
  document.addEventListener('click', (e) => {
3
    if (e.target.classList.contains('dropdown-action')) {
4
      this.hideOtherDropdowns(e.target);
5
      this.handleClick(e.target);
6
    } else {
7
      this.hideOtherDropdowns(null);
8
    }
9
  });
10
}

The initialize() function calls the other functions inside the class. Here I added an event listener to the entire HTML document. We need to do this to respond to a user’s action when they click outside of a given dropdown menu. A good experience is automatically closing the menu when clicking outside of it, so this logic accounts for that.

We can tap into the “click” by using the event that gets returned, and tapping into it for future use. The idea is to use the item the user clicked on to pave the way for showing and hiding the correct menus on the page. If there are multiple menus, we’ll want to close the menus not actively in use automatically.

If the navigation menu link contains the dropdown-action class, we will call two other functions and pass the same target value through to those. Otherwise, we’ll close all other dropdowns using the hideOtherDropdowns() function.

The handleClick() Function

1
  handleClick(dropdownAction) {
2
    this. dropdowns.forEach(dropdown => {
3
      if (dropdown.parentElement.contains(dropdownAction)) {
4
        dropdown.classList.add('active');
5
      } else {
6
        dropdown.classList.remove('active');
7
      }
8
    })
9
  }

The handleClick() function accepts the event.target property. We pass the property from inside the initialize() function. We’ll leverage our previously initialized this.dropdowns array to loop through all dropdowns that exist. If a dropdown contains the event.target (or dropdownAction), we add the class .active to the dropdown menu and show it. If that isn’t the case we will remove the class .active.

The dropdownAction Parameter

1
hideOtherDropdowns(dropdownAction) {
2
  this. dropdowns.forEach((dropdown) => {
3
    if (!dropdown.parentElement.contains(dropdownAction)) {
4
      dropdown.classList.remove('active');
5
    }
6
  });
7
}

Having fewer dropdowns open at once would make for a better experience in the long run. We need to close any that are not actively in use. We can figure out which is used relative to the event.target being passed through from the initialize() function. Here we use a parameter called dropdownAction to sub in for the event.target property.

We’ll loop through all dropdowns once more. Within the forEach loop, we can perform a conditional statement that checks if the dropdown contains the dropdownAction or not. We’ll use the ! to denote that we’ll check the inverse of the logic. So in plain terms, I’m checking if the dropdown does not contain the link to open the dropdown. If not, we’ll remove its active class and hide it.

Conclusion

With any luck, you can now try opening and closing both dropdowns we added in the HTML, and they should respond as we like. When one opens, the other closes. Notice also that when you click outside of a dropdown, the original dropdown menu also closes.

I hope you enjoyed following this JavaScript tutorial, and learned something you can use. Thanks for reading!


This content originally appeared on Envato Tuts+ Tutorials and was authored by Andy Leverenz

In this tutorial, we’ll create a reusable, custom dropdown component, using vanilla JavaScript.

A what? One strategy to reduce a menu or navigation footprint is to place additional links inside a dropdown component. The idea is that users click to reveal more options, thus giving them more ways to navigate web pages, whilst keeping the UI clean.

For this tutorial, I’ll assume we’re building a component for a marketing agency website.

What We Are Building

Here’s our flexible dropdown navigation. Click the items with an arrow to revela the submenus:

How to Build a Dropdown Component With JavaScript

Alright, let’s get stuck in! As usual, we’ll begin with the HTML markup for our srtucture, then we’ll add some styles with CSS, and finally we’ll add the behavior with vanilla JavaScript.

HTML Structure

First, the HTML structure. We will use an unordered list with list items and links.

1
<nav role="primary navigation">
2
  <a href="#">Home</a>
3
  <div class="dropdown">
4
    <a href="#" class="dropdown-action">
5
        Services
6
        <svg class="dropdown-icon" xmlns="https://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><title>chevron-down</title><g fill="none"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.25 10.75L12 14.25l-3.25-3.5"></path></g></svg>
7
    </a>
8
    <ul class="dropdown-menu">
9
      <li><a href="#">SEO</a></li>
10
      <li><a href="#">Content Strategy</a></li>
11
      <li><a href="#">Copywriting</a></li>
12
      <li><a href="#">Storytelling</a></li>
13
    </ul>
14
  </div>
15
  <a href="#">About</a>
16
  <a href="#">Contact</a>
17
  <div class="dropdown">
18
    <a href="#" class="dropdown-action">
19
        Account
20
        <svg class="dropdown-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><title>chevron-down</title><g fill="none"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M15.25 10.75L12 14.25l-3.25-3.5"></path></g></svg>
21
    </a>
22
    <ul class="dropdown-menu">
23
      <li><a href="#">Login</a></li>
24
      <li><a href="#">Sign up</a></li>
25
    </ul>
26
  </div>
27
</nav>
Note the class names on the parent anchor link .dropdown-action and the unordered list .dropdown-menu. These class naming conventions are more generic, so we can reuse the CSS and JavaScript as often as we wish on the website.

Adding Some Styles With CSS

Let’s give the dropdown list some aesthetic treatments with CSS.

Remember that a core foundation of a dropdown is appropriately hiding and showing the list on demand. I’ll design the dropdown list with that in mind.

1
nav {
2
  width: 1020px;
3
  display: flex;
4
  align-items: center;
5
  margin: 20px auto;
6
  padding-bottom: 10px;
7
  border-bottom: 1px solid #ddd;
8
}
9
10
nav a {
11
  padding: 10px 16px;
12
  border-radius: 4px;
13
  display: inline-block;
14
  color: #334155;
15
  text-decoration: none;
16
}
17
18
nav a:hover {
19
  color: #0ea5e9;
20
  background-color: #f0f9ff;
21
}
22
23
.dropdown {
24
  position: relative;
25
}
26
27
.dropdown-action {
28
  display: flex;
29
  align-items: center;
30
  padding-right: 10px;
31
}
32
33
.dropdown-icon {
34
  stroke: currentColor;
35
}
36
37
.dropdown-menu {
38
  display: none;
39
  list-style: none;
40
  margin: 0;
41
  padding: 10px 0;
42
  border: 1px solid #cbd5e1;
43
  border-radius: 6px;
44
  box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
45
  position: absolute;
46
  top: 40px;
47
  left: 5px;
48
  min-width: 180px;
49
  background: white;
50
}
51
52
.dropdown-menu.active {
53
  display: block;
54
}
55
56
.dropdown-menu a {
57
  display: block;
58
}

Adding Interactivity with JavaScript

To make sure we can reuse the dropdown component over and over, I’ll write the JavaScript in a way that will account for any dropdown components on a given page. This means all we need to do is include the script for it to work across many dropdown components assuming the HTML and CSS match our previous work.

1
class Dropdown {
2
3
  constructor() {
4
    this.dropdowns = document.querySelectorAll('.dropdown .dropdown-menu')
5
    if (this. dropdowns.length) {
6
      this.initialize();
7
    }
8
  }
9
10
11
 initialize() {
12
    document.addEventListener('click', (e) => {
13
      if (e.target.classList.contains('dropdown-action')) {
14
        this.hideOtherDropdowns(e.target);
15
        this.handleClick(e.target);
16
      } else {
17
        this.hideOtherDropdowns(null);
18
      }
19
    });
20
  }
21
22
  handleClick(dropdownAction) {
23
    this. dropdowns.forEach(dropdown => {
24
      if (dropdown.parentElement.contains(dropdownAction)) {
25
        dropdown.classList.add('active');
26
      } else {
27
        dropdown.classList.remove('active');
28
      }
29
    })
30
  }
31
32
  hideOtherDropdowns(dropdownAction) {
33
34
    this.dropdowns.forEach((dropdown) => {
35
      if (!dropdown.parentElement.contains(dropdownAction)) {
36
        dropdown.classList.remove('active');
37
      }
38
    });
39
  }
40
41
}
42
43
document.addEventListener('DOMContentLoaded', () => new Dropdown);

Using modern ES6 syntax, I created a new Dropdown class to wrap logic for reuse on a given page. We initialize it at the very in using the following line.

1
document.addEventListener('DOMContentLoaded', () => new Dropdown);

As long as the script is included in a given page, this code is all you need to make the component come alive. We can wait for the DOM content to be loaded before initializing the Dropdown class for better results.

Our Functions (in More Detail)

Let’s break apart each function and dive deeper into what is happening.

The Constructor Method

1
constructor() {
2
  this.dropdowns = document.querySelectorAll('.dropdown .dropdown-menu')
3
  if (this. dropdowns.length) {
4
    this.initialize();
5
  }
6
}

The constructor method is used to initialize the object or class. A constructor enables you to provide any custom initialization before other methods can be called.

Here I added a querySelectorAll method that queries for all dropdown menus on a given page. We’ll loop through those in the coming functions.

Additionally, I added some conditional logic to check that dropdowns exist on a page before calling the initialize() function that is part of the class.

The initialize() Function

1
initialize() {
2
  document.addEventListener('click', (e) => {
3
    if (e.target.classList.contains('dropdown-action')) {
4
      this.hideOtherDropdowns(e.target);
5
      this.handleClick(e.target);
6
    } else {
7
      this.hideOtherDropdowns(null);
8
    }
9
  });
10
}

The initialize() function calls the other functions inside the class. Here I added an event listener to the entire HTML document. We need to do this to respond to a user’s action when they click outside of a given dropdown menu. A good experience is automatically closing the menu when clicking outside of it, so this logic accounts for that.

We can tap into the “click” by using the event that gets returned, and tapping into it for future use. The idea is to use the item the user clicked on to pave the way for showing and hiding the correct menus on the page. If there are multiple menus, we’ll want to close the menus not actively in use automatically.

If the navigation menu link contains the dropdown-action class, we will call two other functions and pass the same target value through to those. Otherwise, we’ll close all other dropdowns using the hideOtherDropdowns() function.

The handleClick() Function

1
  handleClick(dropdownAction) {
2
    this. dropdowns.forEach(dropdown => {
3
      if (dropdown.parentElement.contains(dropdownAction)) {
4
        dropdown.classList.add('active');
5
      } else {
6
        dropdown.classList.remove('active');
7
      }
8
    })
9
  }

The handleClick() function accepts the event.target property. We pass the property from inside the initialize() function. We’ll leverage our previously initialized this.dropdowns array to loop through all dropdowns that exist. If a dropdown contains the event.target (or dropdownAction), we add the class .active to the dropdown menu and show it. If that isn’t the case we will remove the class .active.

The dropdownAction Parameter

1
hideOtherDropdowns(dropdownAction) {
2
  this. dropdowns.forEach((dropdown) => {
3
    if (!dropdown.parentElement.contains(dropdownAction)) {
4
      dropdown.classList.remove('active');
5
    }
6
  });
7
}

Having fewer dropdowns open at once would make for a better experience in the long run. We need to close any that are not actively in use. We can figure out which is used relative to the event.target being passed through from the initialize() function. Here we use a parameter called dropdownAction to sub in for the event.target property.

We’ll loop through all dropdowns once more. Within the forEach loop, we can perform a conditional statement that checks if the dropdown contains the dropdownAction or not. We’ll use the ! to denote that we’ll check the inverse of the logic. So in plain terms, I’m checking if the dropdown does not contain the link to open the dropdown. If not, we’ll remove its active class and hide it.

Conclusion

With any luck, you can now try opening and closing both dropdowns we added in the HTML, and they should respond as we like. When one opens, the other closes. Notice also that when you click outside of a dropdown, the original dropdown menu also closes.

I hope you enjoyed following this JavaScript tutorial, and learned something you can use. Thanks for reading!


This content originally appeared on Envato Tuts+ Tutorials and was authored by Andy Leverenz


Print Share Comment Cite Upload Translate Updates
APA

Andy Leverenz | Sciencx (2022-11-10T18:19:32+00:00) Create a Reusable Dropdown Component with JavaScript. Retrieved from https://www.scien.cx/2022/11/10/create-a-reusable-dropdown-component-with-javascript/

MLA
" » Create a Reusable Dropdown Component with JavaScript." Andy Leverenz | Sciencx - Thursday November 10, 2022, https://www.scien.cx/2022/11/10/create-a-reusable-dropdown-component-with-javascript/
HARVARD
Andy Leverenz | Sciencx Thursday November 10, 2022 » Create a Reusable Dropdown Component with JavaScript., viewed ,<https://www.scien.cx/2022/11/10/create-a-reusable-dropdown-component-with-javascript/>
VANCOUVER
Andy Leverenz | Sciencx - » Create a Reusable Dropdown Component with JavaScript. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/11/10/create-a-reusable-dropdown-component-with-javascript/
CHICAGO
" » Create a Reusable Dropdown Component with JavaScript." Andy Leverenz | Sciencx - Accessed . https://www.scien.cx/2022/11/10/create-a-reusable-dropdown-component-with-javascript/
IEEE
" » Create a Reusable Dropdown Component with JavaScript." Andy Leverenz | Sciencx [Online]. Available: https://www.scien.cx/2022/11/10/create-a-reusable-dropdown-component-with-javascript/. [Accessed: ]
rf:citation
» Create a Reusable Dropdown Component with JavaScript | Andy Leverenz | Sciencx | https://www.scien.cx/2022/11/10/create-a-reusable-dropdown-component-with-javascript/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.