In my experience, dropdown tutorials usually fall into one of two categories:
-
Fairly small in scope, but very dated looking
-
Very pretty, but overcomplicated with a lot of JavaScript
Thankfully, I find there’s a nice middle ground for simple but stylish dropdown menus. In this example, we’ll use mostly CSS with a sprinkle of JavaScript to glue everything together. You can view the final example on Codepen.
HTML
To start, we add the HTML structure of our navigation bar with dropdown. We include a dropdown toggle and a list of dropdown items.
<nav class="nav">
<span class="logo">A Company</span>
<div class="dropdown">
<div class="dropdown__toggle">
<span>User Name</span>
<i class="fas fa-angle-down toggle__indicator"></i>
</div>
<ul class="dropdown__items">
<li><a href="#" class="dropdown__item">Profile</a></li>
<li><a href="#" class="dropdown__item">Settings</a></li>
<li><a href="#" class="dropdown__item">Log Out</a></li>
</ul>
</div>
</nav>
JavaScript
Now we add our JavaScript to act as the glue between our CSS and HTML.
When a visitor clicks on the dropdown toggle, classes are applied to the dropdown indicator and items list. When the window is clicked, as long as the user isn’t clicking on the dropdown, these active classes are removed.
var dropdown = document.querySelector(".dropdown");
var toggle = document.querySelector(".dropdown__toggle");
var indicator = document.querySelector(".toggle__indicator");
var items = document.querySelector(".dropdown__items");
toggle.addEventListener("click", () => {
indicator.classList.toggle("toggle__indicator_active");
items.classList.toggle("dropdown__items_active");
});
window.addEventListener("click", (e) => {
if (dropdown.contains(e.target)) {
return;
}
indicator.classList.remove("toggle__indicator_active");
items.classList.remove("dropdown__items_active");
});
CSS
After defining some styles for the page and the navigation bar, we dig into the dropdown styles. We define base styles for the toggle, indicator, and items. Additionally, we add styles for the active classes mentioned in the previous section. These styles define what an active, or open, dropdown menu looks like.
A few areas of note:
-
In the
body
styles, we set-webkit-font-smoothing
toantialiased
to prevent jittering animation when revealing the dropdown items in WebKit browsers -
In the dropdown items active class,
.dropdown__items_active
, we settransform
totranslateY(5px)
to give the feeling that the dropdown items are dropping out of the toggle -
In the indicator active class,
.toggle__indicator_active
, we settransform
torotate(180deg)
to rotate the downward facing arrow 180 degrees
html,
body {
-webkit-font-smoothing: antialiased;
background: #fff;
padding: 4rem;
}
.nav {
display: flex;
justify-content: space-between;
margin: 0 auto;
max-width: 400px;
text-align: center;
}
.dropdown {
position: relative;
}
.dropdown__toggle {
align-items: center;
cursor: pointer;
display: flex;
justify-content: space-between;
}
.toggle__indicator {
-webkit-transform: rotate(0);
margin-left: 0.5rem;
transform: rotate(0deg);
transition: all 0.25s ease;
}
.toggle__indicator_active {
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
.dropdown__items {
-webkit-padding-start: 0;
background: #fff;
border-radius: 3px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
list-style: none;
margin-top: 5px;
min-width: 8rem;
opacity: 0;
pointer-events: none;
position: absolute;
right: 0;
transition: all 0.25s ease;
white-space: nowrap;
z-index: 1;
}
.dropdown__items_active {
-webkit-transform: translateY(5px);
opacity: 1;
pointer-events: auto;
transform: translateY(5px);
}
.dropdown__item {
color: #000;
display: block;
padding: 1rem;
text-decoration: none;
transition: all 0.3s ease;
}
.dropdown__item:hover {
background: #eef6fc;
color: #2753a5;
}