Feature Coming Soon!
The newsletter functionality is under development.
This project demonstrates how to create a highly interactive and visually appealing dropdown menu using HTML, CSS, and JavaScript. The dropdown is not just functional but also features smooth animations and a unique floating icon effect that follows the cursor, providing a delightful user experience.
The menu items are dynamically generated using JavaScript, making it easy to add, remove, or change the options. When an item is selected, the main button updates to reflect the choice, both in text and with a corresponding icon. The entire component is styled with a modern, dark theme and utilizes CSS custom properties for easy customization of colors, animations, and dimensions.
Let's start with the basic HTML for the Dropdown Menu.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Dropdown Menu | Coders_Section</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="dropdown-container">
<button class="dropdown-button main-button">
<span class="dropdown-title-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path d="M16 8.049c0-4.446-3.582-8.05-8-8.05C3.58 0-.002 3.603-.002 8.05c0 4.017 2.926 7.347 6.75 7.951v-5.625h-2.03V8.05H6.75V6.275c0-2.017 1.195-3.131 3.022-3.131.876 0 1.791.157 1.791.157v1.98h-1.009c-.993 0-1.303.621-1.303 1.258v1.51h2.218l-.354 2.326H9.25V16c3.824-.604 6.75-3.934 6.75-7.951z" />
</svg>
</span>
<span class="dropdown-title text-truncate">Facebook</span>
<span class="dropdown-arrow">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path d="M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z" />
</svg>
</span>
</button>
<div class="dropdown-list-container">
<div class="dropdown-list-wrapper">
<ul class="dropdown-list"></ul>
<div class="floating-icon" aria-hidden="true"></div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Here's the CSS that creates the animated dropdown and floating icon effect.
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root {
--bg-color: #000000;
--primary-bg-color: #333740;
--primary-color: #00fbff;
--text-color: #b1b8ca;
--text-active: #ffffff;
--button-hover-bg-color: #2b2e34;
--border-color: #494d59;
--dropdown-height: 0;
--rotate-arrow: 0;
--translate-value: 0;
--list-opacity: 0;
--transition-time: 0.4s;
--transition-timing: cubic-bezier(0.25, 0.46, 0.45, 0.94);
--border-radius: 1.4rem;
--list-button-height: 4.6rem;
--floating-icon-size: 26;
--floating-icon-top: 0;
--floating-icon-left: 0;
}
html {
font-size: 62.5%;
}
html,
body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
align-items: center;
background-color: var(--bg-color);
padding: 1.5rem;
line-height: 1.4;
}
button {
border: none;
cursor: pointer;
background-color: transparent;
outline: none;
}
svg {
height: 1.6rem;
width: 1.6rem;
}
.text-truncate {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
}
.dropdown-container {
margin-top: 30vh;
display: flex;
flex-direction: column;
width: 100%;
max-width: 34rem;
}
.dropdown-title-icon,
.dropdown-arrow {
display: inline-flex;
}
.dropdown-title {
margin: 0 auto 0 1.8rem;
text-transform: capitalize;
}
.dropdown-button {
font-family: "Roboto", sans-serif;
font-weight: 400;
font-size: 1.7rem;
display: flex;
align-items: center;
padding: 0 1.8rem;
}
.dropdown-button svg {
transition: all var(--transition-time) var(--transition-timing);
fill: var(--text-color);
}
.dropdown-button svg,
.dropdown-button span {
pointer-events: none;
}
.dropdown-button:hover,
.dropdown-button:focus {
color: var(--text-active);
}
.dropdown-button:hover svg,
.dropdown-button:focus svg {
fill: var(--text-active);
}
.main-button {
height: 5.2rem;
border-radius: var(--border-radius);
color: var(--text-color);
background-color: var(--primary-bg-color);
border: 0.1rem solid var(--border-color);
transition: all var(--transition-time) var(--transition-timing);
}
.main-button:focus {
border: 0.1rem solid var(--primary-color);
box-shadow: 0 0 0 0.2rem rgba(44, 98, 246, 0.4);
}
.main-button .dropdown-arrow {
transition: transform var(--transition-time) var(--transition-timing);
transform: rotate(var(--rotate-arrow));
margin-left: 1.8rem;
}
.list-button {
height: var(--list-button-height);
transition: color var(--transition-time) var(--transition-timing);
color: var(--text-color);
overflow: hidden;
cursor: none;
}
.dropdown-list-container {
overflow: hidden;
max-height: var(--dropdown-height);
transition: max-height var(--transition-time) var(--transition-timing);
}
.dropdown-list-wrapper {
margin-top: 1rem;
padding: 1rem;
background-color: var(--primary-bg-color);
border-radius: var(--border-radius);
border: 0.1rem solid var(--border-color);
position: relative;
}
ul.dropdown-list {
position: relative;
list-style-type: none;
}
ul.dropdown-list::before {
content: "";
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 0;
opacity: 0;
height: var(--list-button-height);
background-color: var(--button-hover-bg-color);
transition: all var(--transition-time) linear;
transform: translateY(var(--translate-value));
border-radius: var(--border-radius);
pointer-events: none;
}
ul.dropdown-list:hover::before,
ul.dropdown-list:hover ~ .floating-icon {
opacity: 1;
}
li.dropdown-list-item {
display: flex;
flex-direction: column;
position: relative;
z-index: 1;
opacity: var(--list-opacity);
transition: opacity 0.8s var(--transition-timing);
}
.floating-icon {
height: calc(var(--floating-icon-size) * 1px);
width: calc(var(--floating-icon-size) * 1px);
position: absolute;
top: var(--floating-icon-top);
left: var(--floating-icon-left);
background-color: var(--border-color);
border-radius: 1rem;
pointer-events: none;
opacity: 0;
transition: opacity var(--transition-time) var(--transition-timing);
z-index: 2;
display: inline-flex;
align-items: center;
justify-content: center;
}
.floating-icon svg {
fill: var(--text-active);
}
The JavaScript handles the dynamic creation of list items and the interactive animations.
const root = document.documentElement;
const dropdownTitleIcon = document.querySelector(".dropdown-title-icon");
const dropdownTitle = document.querySelector(".dropdown-title");
const dropdownList = document.querySelector(".dropdown-list");
const mainButton = document.querySelector(".main-button");
const floatingIcon = document.querySelector(".floating-icon");
const icons = {
linkedin: "M0 1.146C0 .513.526 0 1.175 0h13.65C15.474 0 16 .513 16 1.146v13.708c0 .633-.526 1.146-1.175 1.146H1.175C.526 16 0 15.487 0 14.854V1.146zm4.943 12.248V6.169H2.542v7.225h2.401zm-1.2-8.212c.837 0 1.358-.554 1.358-1.248-.015-.709-.52-1.248-1.342-1.248-.822 0-1.359.54-1.359 1.248 0 .694.521 1.248 1.327 1.248h.016zm4.908 8.212V9.359c0-.216.016-.432.08-.586.173-.431.568-.878 1.232-.878.869 0 1.216.662 1.216 1.634v3.865h2.401V9.25c0-2.22-1.184-3.252-2.764-3.252-1.274 0-1.845.7-2.165 1.193v.025h-.016a5.54 5.54 0 0 1 .016-.025V6.169h-2.4c.03.678 0 7.225 0 7.225h2.4z",
instagram: "M8 0C5.829 0 5.556.01 4.703.048 3.85.088 3.269.222 2.76.42a3.917 3.917 0 0 0-1.417.923A3.927 3.927 0 0 0 .42 2.76C.222 3.268.087 3.85.048 4.7.01 5.555 0 5.827 0 8.001c0 2.172.01 2.444.048 3.297.04.852.174 1.433.372 1.942.205.526.478.972.923 1.417.444.445.89.719 1.416.923.51.198 1.09.333 1.942.372C5.555 15.99 5.827 16 8 16s2.444-.01 3.298-.048c.851-.04 1.434-.174 1.943-.372a3.916 3.916 0 0 0 1.416-.923c.445-.445.718-.891.923-1.417.197-.509.332-1.09.372-1.942C15.99 10.445 16 10.173 16 8s-.01-2.445-.048-3.299c-.04-.851-.175-1.433-.372-1.941a3.926 3.926 0 0 0-.923-1.417A3.911 3.911 0 0 0 13.24.42c-.51-.198-1.092-.333-1.943-.372C10.443.01 10.172 0 7.998 0h.003zm-.717 1.442h.718c2.136 0 2.389.007 3.232.046.78.035 1.204.166 1.486.275.373.145.64.319.92.599.28.28.453.546.598.92.11.281.24.705.275 1.485.039.843.047 1.096.047 3.231s-.008 2.389-.047 3.232c-.035.78-.166 1.203-.275 1.485a2.47 2.47 0 0 1-.599.919c-.28.28-.546.453-.92.598-.28.11-.704.24-1.485.276-.843.038-1.096.047-3.232.047s-2.39-.009-3.233-.047c-.78-.036-1.203-.166-1.485-.276a2.478 2.478 0 0 1-.92-.598 2.48 2.48 0 0 1-.6-.92c-.109-.281-.24-.705-.275-1.485-.038-.843-.046-1.096-.046-3.233 0-2.136.008-2.388.046-3.231.036-.78.166-1.204.276-1.486.145-.373.319-.64.599-.92.28-.28.546-.453.92-.598.282-.11.705-.24 1.485-.276.738-.034 1.024-.044 2.515-.045v.002zm4.988 1.328a.96.96 0 1 0 0 1.92.96.96 0 0 0 0-1.92zm-4.27 1.122a4.109 4.109 0 1 0 0 8.217 4.109 4.109 0 0 0 0-8.217zm0 1.441a2.667 2.667 0 1 1 0 5.334 2.667 2.667 0 0 1 0-5.334z",
facebook: "M16 8.049c0-4.446-3.582-8.05-8-8.05C3.58 0-.002 3.603-.002 8.05c0 4.017 2.926 7.347 6.75 7.951v-5.625h-2.03V8.05H6.75V6.275c0-2.017 1.195-3.131 3.022-3.131.876 0 1.791.157 1.791.157v1.98h-1.009c-.993 0-1.303.621-1.303 1.258v1.51h2.218l-.354 2.326H9.25V16c3.824-.604 6.75-3.934 6.75-7.951z",
twitter: "M5.026 15c6.038 0 9.341-5.003 9.341-9.334 0-.14 0-.282-.006-.422A6.685 6.685 0 0 0 16 3.542a6.658 6.658 0 0 1-1.889.518 3.301 3.301 0 0 0 1.447-1.817 6.533 6.533 0 0 1-2.087.793A3.286 3.286 0 0 0 7.875 6.03a9.325 9.325 0 0 1-6.767-3.429 3.289 3.289 0 0 0 1.018 4.382A3.323 3.323 0 0 1 .64 6.575v.045a3.288 3.288 0 0 0 2.632 3.218 3.203 3.203 0 0 1-.865.115 3.23 3.23 0 0 1-.614-.057 3.283 3.283 0 0 0 3.067 2.277A6.588 6.588 0 0 1 .78 13.58a6.32 6.32 0 0 1-.78-.045A9.344 9.344 0 0 0 5.026 15z",
youtube: "M8.051 1.999h.089c.822.003 4.987.033 6.11.335a2.01 2.01 0 0 1 1.415 1.42c.101.38.172.883.22 1.402l.01.104.022.26.008.104c.065.914.073 1.77.074 1.957v.075c-.001.194-.01 1.108-.082 2.06l-.008.105-.009.104c-.05.572-.124 1.14-.235 1.558a2.007 2.007 0 0 1-1.415 1.42c-1.16.312-5.569.334-6.18.335h-.142c-.309 0-1.587-.006-2.927-.052l-.17-.006-.087-.004-.171-.007-.171-.007c-1.11-.049-2.167-.128-2.654-.26a2.007 2.007 0 0 1-1.415-1.419c-.111-.417-.185-.986-.235-1.558L.09 9.82l-.008-.104A31.4 31.4 0 0 1 0 7.68v-.123c.002-.215.01-.958.064-1.778l.007-.103.003-.052.008-.104.022-.26.01-.104c.048-.519.119-1.023.22-1.402a2.007 2.007 0 0 1 1.415-1.42c.487-.13 1.544-.21 2.654-.26l.17-.007.172-.006.086-.003.171-.007A99.788 99.788 0 0 1 7.858 2h.193zM6.4 5.209v4.818l4.157-2.408L6.4 5.209z"
};
const listItems = ["Linkedin", "Instagram", "Facebook", "Twitter", "Youtube"];
const iconTemplate = (path) => {
return `
`;
};
const listItemTemplate = (text, translateValue) => {
return `
`;
};
const renderListItems = () => {
dropdownList.innerHTML += listItems
.map((item, index) => {
return listItemTemplate(item, 100 * index);
})
.join("");
};
window.addEventListener("load", () => {
renderListItems();
});
const setDropdownProps = (deg, ht, opacity) => {
root.style.setProperty("--rotate-arrow", deg !== 0 ? deg + "deg" : 0);
root.style.setProperty("--dropdown-height", ht !== 0 ? ht + "rem" : 0);
root.style.setProperty("--list-opacity", opacity);
};
mainButton.addEventListener("click", () => {
const listWrapperSizes = 3.5; // margins, paddings & borders
const dropdownOpenHeight = 4.6 * listItems.length + listWrapperSizes;
const currDropdownHeight =
root.style.getPropertyValue("--dropdown-height") || "0";
currDropdownHeight === "0"
? setDropdownProps(180, dropdownOpenHeight, 1)
: setDropdownProps(0, 0, 0);
});
dropdownList.addEventListener("mouseover", (e) => {
const translateValue = e.target.dataset.translateValue;
root.style.setProperty("--translate-value", translateValue);
});
dropdownList.addEventListener("click", (e) => {
const clickedItemText = e.target.innerText.toLowerCase().trim();
const clickedItemIcon = icons[clickedItemText];
dropdownTitleIcon.innerHTML = iconTemplate(clickedItemIcon);
dropdownTitle.innerHTML = clickedItemText;
setDropdownProps(0, 0, 0);
});
dropdownList.addEventListener("mousemove", (e) => {
const iconSize = root.style.getPropertyValue("--floating-icon-size") || 0;
const x = e.clientX - dropdownList.getBoundingClientRect().x;
const y = e.clientY - dropdownList.getBoundingClientRect().y;
const targetText = e.target.innerText.toLowerCase().trim();
const hoverItemText = icons[targetText];
floatingIcon.innerHTML = iconTemplate(hoverItemText);
root.style.setProperty("--floating-icon-left", x - iconSize / 2 + "px");
root.style.setProperty("--floating-icon-top", y - iconSize / 2 + "px");
});
Watch a live demonstration of the Dropdown Menu below.
This custom dropdown menu is a perfect example of how thoughtful design and modern web technologies can elevate a simple UI component. The combination of dynamic JavaScript for content and advanced CSS for animations results in a component that is both functional and engaging. It's a lightweight and performant solution for navigation menus, social links, or any selection-based interface.
You can easily customize this component by:
Leverage CSS Custom Properties for Theming. This project makes extensive use of variables like --primary-bg-color
and --transition-time
. By centralizing these values, you can change the entire look and feel of the dropdown in seconds without searching for individual styles.
Click the button below to download the full source code. Download will be ready in 10 seconds.
Receive coding tips and resources updates. No spam.
We respect your privacy. Unsubscribe at any time.