<div class="custom-select">
<div class="select-trigger">
<span class="selected-text">Select a Country</span>
<svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none">
<polyline points="6 9 12 15 18 9"></polyline>
</svg>
</div>
<div class="options-container">
<input type="text" class="search-box" placeholder="Search..." autofocus>
<ul class="options-list">
<li data-value="us">United States</li>
<li data-value="ca">Canada</li>
<li data-value="uk">United Kingdom</li>
<li data-value="au">Australia</li>
<li data-value="de">Germany</li>
<li data-value="fr">France</li>
<li data-value="jp">Japan</li>
</ul>
</div>
</div>
* { box-sizing: border-box; }
body {
font-family: system-ui, "Segoe UI", sans-serif;
background: #f1f5f9;
height: 100vh;
display: flex;
justify-content: center;
align-items: flex-start;
padding-top: 100px;
}
.custom-select {
position: relative;
width: 300px;
user-select: none;
}
.select-trigger {
background: white;
padding: 12px 16px;
border-radius: 8px;
border: 1px solid #cbd5e1;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
transition: 0.2s;
}
.select-trigger:hover { border-color: #94a3b8; }
.options-container {
position: absolute;
top: 100%;
left: 0;
width: 100%;
background: white;
border: 1px solid #cbd5e1;
border-radius: 8px;
margin-top: 8px;
box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1);
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: 0.2s;
z-index: 10;
overflow: hidden;
}
.custom-select.open .options-container {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.search-box {
width: 100%;
padding: 12px;
border: none;
border-bottom: 1px solid #f1f5f9;
outline: none;
font-size: 14px;
}
.options-list {
list-style: none;
padding: 0;
margin: 0;
max-height: 200px;
overflow-y: auto;
}
.options-list li {
padding: 10px 16px;
cursor: pointer;
transition: 0.2s;
}
.options-list li:hover { background: #f8fafc; }
.options-list li.hidden { display: none; }
const wrapper = document.querySelector(".custom-select");
const trigger = document.querySelector(".select-trigger");
const selectedText = document.querySelector(".selected-text");
const searchBox = document.querySelector(".search-box");
const options = document.querySelectorAll(".options-list li");
// Toggle dropdown
trigger.addEventListener("click", () => {
wrapper.classList.toggle("open");
if(wrapper.classList.contains("open")) searchBox.focus();
});
// Select option
options.forEach(option => {
option.addEventListener("click", () => {
selectedText.innerText = option.innerText;
wrapper.classList.remove("open");
// Reset search
searchBox.value = "";
filterOptions("");
});
});
// Search filter
searchBox.addEventListener("input", (e) => filterOptions(e.target.value));
function filterOptions(query) {
const lowerQuery = query.toLowerCase();
options.forEach(option => {
const text = option.innerText.toLowerCase();
if(text.includes(lowerQuery)) {
option.classList.remove("hidden");
} else {
option.classList.add("hidden");
}
});
}
// Close outside click
document.addEventListener("click", (e) => {
if(!wrapper.contains(e.target)) wrapper.classList.remove("open");
});