CSS Dropdowns - Dropdown Menu
A dropdown is a UI component that hides its content and reveals it when the user interacts (clicks/hovers). Dropdowns are commonly used in navigation menus, custom form selects, and action menus.
CSS Dropdowns make use of the :hover and :focus pseudo-classes, position: absolute, z-index, and transition for animation effects. For accessibility, it is also important to handle :focus states so that the dropdown can be used with a keyboard.
Basic technique: hide the dropdown content with opacity: 0 + visibility: hidden, then reveal it when the parent is hovered with a smooth transition.
Code Example
Comprehensive Dropdown
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Dropdowns</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, sans-serif;
padding: 30px;
background: #f0f2f5;
color: #334155;
}
h2 {
margin-bottom: 15px;
color: #1a1a2e;
}
.section {
margin-bottom: 50px;
}
.label {
font-size: 12px;
color: #64748b;
margin-bottom: 10px;
font-family: monospace;
background: #e2e8f0;
display: inline-block;
padding: 3px 8px;
border-radius: 4px;
margin-top: 10px;
margin-bottom: 15px;
}
/* ===== DROPDOWN BASE ===== */
.dropdown {
position: relative;
display: inline-block;
}
.dropdown-trigger {
padding: 12px 24px;
background: #667eea;
color: white;
border: none;
border-radius: 8px;
font-size: 15px;
font-weight: 600;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: background 0.3s;
}
.dropdown-trigger:hover {
background: #5a67d8;
}
.dropdown-trigger::after {
content: '▾';
font-size: 12px;
}
.dropdown-menu {
position: absolute;
top: calc(100% + 8px);
left: 0;
background: white;
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0,0,0,0.12);
min-width: 220px;
padding: 8px;
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: all 0.3s;
z-index: 100;
}
.dropdown:hover .dropdown-menu,
.dropdown:focus-within .dropdown-menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.dropdown-menu::before {
content: '';
position: absolute;
top: -6px;
left: 20px;
width: 12px;
height: 12px;
background: white;
transform: rotate(45deg);
box-shadow: -2px -2px 4px rgba(0,0,0,0.05);
}
.dropdown-menu a,
.dropdown-menu button {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 14px;
color: #475569;
text-decoration: none;
border-radius: 8px;
font-size: 14px;
transition: all 0.2s;
border: none;
background: none;
width: 100%;
cursor: pointer;
text-align: left;
}
.dropdown-menu a:hover,
.dropdown-menu button:hover {
background: #f1f5f9;
color: #667eea;
}
.dropdown-menu a:focus-visible,
.dropdown-menu button:focus-visible {
outline: 2px solid #667eea;
outline-offset: -2px;
background: #eef2ff;
}
.dropdown-divider {
height: 1px;
background: #e2e8f0;
margin: 6px 0;
}
.dropdown-menu .icon {
width: 18px;
text-align: center;
font-size: 14px;
}
.dropdown-menu .danger {
color: #dc2626;
}
.dropdown-menu .danger:hover {
background: #fef2f2;
color: #dc2626;
}
/* ===== NAV DROPDOWN ===== */
.nav-bar {
display: flex;
align-items: center;
gap: 5px;
background: #1a1a2e;
padding: 10px 20px;
border-radius: 12px;
}
.nav-item {
position: relative;
}
.nav-item > a {
color: #cbd5e1;
text-decoration: none;
padding: 10px 18px;
border-radius: 8px;
font-weight: 500;
display: flex;
align-items: center;
gap: 6px;
transition: all 0.3s;
}
.nav-item > a::after {
content: '▾';
font-size: 10px;
transition: transform 0.3s;
}
.nav-item:hover > a::after,
.nav-item:focus-within > a::after {
transform: rotate(180deg);
}
.nav-item > a:hover,
.nav-item > a:focus-visible {
background: rgba(255,255,255,0.1);
color: white;
}
.nav-dropdown {
position: absolute;
top: calc(100% + 8px);
left: 0;
background: white;
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0,0,0,0.15);
min-width: 200px;
padding: 8px;
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: all 0.3s;
z-index: 1000;
}
.nav-item:hover .nav-dropdown,
.nav-item:focus-within .nav-dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.nav-dropdown a {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 14px;
color: #475569;
text-decoration: none;
border-radius: 8px;
font-size: 14px;
transition: all 0.2s;
}
.nav-dropdown a:hover {
background: #f1f5f9;
color: #667eea;
}
.nav-dropdown .nav-icon {
width: 20px;
text-align: center;
}
.nav-dropdown .nav-desc {
font-size: 11px;
color: #94a3b8;
margin-top: 2px;
}
.nav-dropdown .nav-group-title {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.5px;
color: #94a3b8;
padding: 10px 14px 4px;
font-weight: 600;
}
/* ===== USER MENU ===== */
.user-menu-container {
display: flex;
justify-content: flex-end;
}
.user-menu {
position: relative;
}
.user-menu-trigger {
display: flex;
align-items: center;
gap: 10px;
padding: 6px 12px;
background: white;
border: 2px solid #e2e8f0;
border-radius: 50px;
cursor: pointer;
transition: border-color 0.3s;
}
.user-menu-trigger:hover {
border-color: #667eea;
}
.user-menu-avatar {
width: 36px;
height: 36px;
border-radius: 50%;
background: linear-gradient(135deg, #667eea, #764ba2);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
font-size: 14px;
}
.user-menu-name {
font-weight: 600;
color: #1e293b;
font-size: 14px;
}
.user-menu-arrow {
color: #94a3b8;
font-size: 12px;
transition: transform 0.3s;
}
.user-menu:hover .user-menu-arrow {
transform: rotate(180deg);
}
.user-dropdown {
position: absolute;
top: calc(100% + 10px);
right: 0;
background: white;
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0,0,0,0.12);
min-width: 240px;
padding: 8px;
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: all 0.3s;
z-index: 100;
}
.user-menu:hover .user-dropdown,
.user-menu:focus-within .user-dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.user-dropdown-header {
padding: 12px 14px;
border-bottom: 1px solid #e2e8f0;
margin-bottom: 6px;
}
.user-dropdown-header .name {
font-weight: 600;
color: #1e293b;
}
.user-dropdown-header .email {
font-size: 12px;
color: #94a3b8;
}
.user-dropdown a,
.user-dropdown button {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 14px;
color: #475569;
text-decoration: none;
border-radius: 8px;
font-size: 14px;
transition: all 0.2s;
width: 100%;
border: none;
background: none;
cursor: pointer;
text-align: left;
}
.user-dropdown a:hover,
.user-dropdown button:hover {
background: #f1f5f9;
color: #667eea;
}
.user-dropdown .dd-icon {
width: 18px;
text-align: center;
}
.user-dropdown .danger:hover {
background: #fef2f2;
color: #dc2626;
}
/* ===== CUSTOM SELECT DROPDOWN ===== */
.custom-select-wrapper {
position: relative;
width: 300px;
}
.custom-select {
width: 100%;
padding: 12px 40px 12px 16px;
border: 2px solid #e2e8f0;
border-radius: 10px;
font-size: 15px;
background: white;
appearance: none;
cursor: pointer;
transition: border-color 0.3s;
}
.custom-select:focus {
border-color: #667eea;
outline: none;
}
.custom-select-arrow {
position: absolute;
right: 14px;
top: 50%;
transform: translateY(-50%);
color: #94a3b8;
pointer-events: none;
font-size: 14px;
}
/* ===== RIGHT-ALIGNED DROPDOWN ===== */
.dropdown-right .dropdown-menu {
left: auto;
right: 0;
}
.dropdown-right .dropdown-menu::before {
left: auto;
right: 20px;
}
/* ===== CONTEXT MENU STYLE ===== */
.context-area {
width: 100%;
height: 300px;
background: white;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
color: #94a3b8;
border: 2px dashed #e2e8f0;
user-select: none;
}
</style>
</head>
<body>
<!-- Basic Dropdown -->
<div class="section">
<h2>Basic Dropdown</h2>
<span class="label">opacity + visibility + transform + z-index</span>
<div class="dropdown">
<button class="dropdown-trigger">Select Action</button>
<div class="dropdown-menu">
<a href="#"><span class="icon">✏️</span> Edit Profile</a>
<a href="#"><span class="icon">⚙️</span> Settings</a>
<a href="#"><span class="icon">📊</span> Dashboard</a>
<div class="dropdown-divider"></div>
<a href="#"><span class="icon">💬</span> Message</a>
<a href="#"><span class="icon">🔔</span> Notifikasi</a>
<div class="dropdown-divider"></div>
<a href="#" class="danger"><span class="icon">🚪</span> Log Out</a>
</div>
</div>
</div>
<!-- Nav Dropdown -->
<div class="section">
<h2>Navigation Dropdown</h2>
<span class="label">position: absolute + :hover + :focus-within</span>
<nav class="nav-bar">
<div class="nav-item">
<a href="#">Home</a>
</div>
<div class="nav-item">
<a href="#">Products</a>
<div class="nav-dropdown">
<div class="nav-group-title">Kategori</div>
<a href="#">
<span class="nav-icon">💻</span>
<div>
<div>Technology</div>
<div class="nav-desc">Tutorial programming</div>
</div>
</a>
<a href="#">
<span class="nav-icon">🎨</span>
<div>
<div>Desain</div>
<div class="nav-desc">UI/UX & Grafis</div>
</div>
</a>
<a href="#">
<span class="nav-icon">📈</span>
<div>
<div>Bisnis</div>
<div class="nav-desc">Strategi & Marketing</div>
</div>
</a>
<a href="#">
<span class="nav-icon">📸</span>
<div>
<div>Photos & Videos</div>
<div class="nav-desc">Editing & Production</div>
</div>
</a>
</div>
</div>
<div class="nav-item">
<a href="#">Mentor</a>
</div>
<div class="nav-item">
<a href="#">More</a>
<div class="nav-dropdown">
<a href="#"><span class="nav-icon">📖</span> Blog</a>
<a href="#"><span class="nav-icon">❓</span> FAQ</a>
<a href="#"><span class="nav-icon">📞</span> Kontak</a>
<a href="#"><span class="nav-icon">📋</span> Syarat & Ketentuan</a>
</div>
</div>
</nav>
</div>
<!-- User Menu -->
<div class="section">
<h2>User Menu Dropdown</h2>
<span class="label">position: absolute right + focus-within</span>
<div class="user-menu-container">
<div class="user-menu">
<button class="user-menu-trigger">
<div class="user-menu-avatar">BS</div>
<span class="user-menu-name">John Smith</span>
<span class="user-menu-arrow">▾</span>
</button>
<div class="user-dropdown">
<div class="user-dropdown-header">
<div class="name">John Smith</div>
<div class="email">[email protected]</div>
</div>
<a href="#"><span class="dd-icon">👤</span> My Profile</a>
<a href="#"><span class="dd-icon">⚙️</span> Settings</a>
<a href="#"><span class="dd-icon">📊</span> Dashboard</a>
<a href="#"><span class="dd-icon">💳</span> Langganan</a>
<div class="dropdown-divider"></div>
<a href="#"><span class="dd-icon">❓</span> Bantuan</a>
<button class="danger"><span class="dd-icon">🚪</span> Log Out</button>
</div>
</div>
</div>
</div>
<!-- Custom Select -->
<div class="section">
<h2>Custom Select Dropdown</h2>
<span class="label">appearance: none + custom arrow</span>
<div class="custom-select-wrapper">
<select class="custom-select">
<option value="">Select Programming Language</option>
<option value="html">HTML</option>
<option value="css">CSS</option>
<option value="javascript">JavaScript</option>
<option value="python">Python</option>
<option value="java">Java</option>
<option value="go">Go</option>
<option value="rust">Rust</option>
</select>
<span class="custom-select-arrow">▾</span>
</div>
</div>
<!-- Right-Aligned -->
<div class="section">
<h2>Right-Aligned Dropdown</h2>
<span class="label">left: auto; right: 0;</span>
<div style="display: flex; justify-content: flex-end;">
<div class="dropdown dropdown-right">
<button class="dropdown-trigger">Opsi ⚙️</button>
<div class="dropdown-menu">
<a href="#"><span class="icon">📋</span> Copy Link</a>
<a href="#"><span class="icon">📤</span> Share</a>
<a href="#"><span class="icon">⬇️</span> Download</a>
<div class="dropdown-divider"></div>
<a href="#" class="danger"><span class="icon">🗑️</span> Delete</a>
</div>
</div>
</div>
</div>
</body>
</html>
Code Explanation
Hidden Default State
The dropdown content is hidden with a combination of three properties:
.dropdown-menu {
opacity: 0; /* Transparent */
visibility: hidden; /* Not clickable */
transform: translateY(-10px); /* Slightly upward */
transition: all 0.3s; /* Smooth animation */
}
Why not display: none? Because display: none cannot be animated. The combination of opacity + visibility allows a smooth transition.
Hover Reveal
Shows the dropdown when the parent is hovered:
.dropdown:hover .dropdown-menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
position: absolute
The dropdown menu must be taken out of the document flow so it does not affect the other layout:
.dropdown {
position: relative; /* Anchor for the dropdown */
}
.dropdown-menu {
position: absolute; /* Floating */
top: calc(100% + 8px); /* 8px below the trigger */
left: 0;
}
z-index
Ensures the dropdown sits above other content:
.dropdown-menu {
z-index: 100;
}
Stacking Context Scale:
- Dropdown: z-index: 1000
- Sticky: 1020
- Fixed: 1030
- Modal: 1040
- Popover: 1050
- Toast: 1060
:focus-within
Important for accessibility — the dropdown stays open when an element inside it is focused with the keyboard:
.dropdown:hover .dropdown-menu,
.dropdown:focus-within .dropdown-menu {
opacity: 1;
visibility: visible;
}
transition
Smooth animation effects:
.dropdown-menu {
transition: opacity 0.3s, visibility 0.3s, transform 0.3s;
}
Everyday Use Cases
1. Action Dropdown in a Table
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
.table-wrapper {
padding: 20px;
background: white;
border-radius: 12px;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
max-width: 700px;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 14px 16px;
text-align: left;
border-bottom: 1px solid #e2e8f0;
}
th {
background: #f8fafc;
font-weight: 600;
color: #475569;
font-size: 13px;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.action-cell {
position: relative;
}
.action-btn {
padding: 6px 12px;
background: #f1f5f9;
border: 1px solid #e2e8f0;
border-radius: 6px;
cursor: pointer;
font-size: 13px;
transition: all 0.2s;
}
.action-btn:hover {
background: #e2e8f0;
}
.action-dropdown {
position: absolute;
top: calc(100% + 4px);
right: 0;
background: white;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.12);
min-width: 160px;
padding: 6px;
opacity: 0;
visibility: hidden;
transform: translateY(-5px);
transition: all 0.2s;
z-index: 50;
}
.action-cell:hover .action-dropdown {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.action-dropdown a {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
color: #475569;
text-decoration: none;
border-radius: 6px;
font-size: 13px;
transition: all 0.2s;
}
.action-dropdown a:hover {
background: #f1f5f9;
color: #667eea;
}
.action-dropdown .del:hover {
background: #fef2f2;
color: #dc2626;
}
</style>
</head>
<body>
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>John Smith</td>
<td>[email protected]</td>
<td>Active</td>
<td class="action-cell">
<button class="action-btn">⋯</button>
<div class="action-dropdown">
<a href="#">✏️ Edit</a>
<a href="#">👁️ View</a>
<a href="#">📋 Duplikat</a>
<a href="#">📤 Ekspor</a>
<div style="height:1px;background:#e2e8f0;margin:4px 0;"></div>
<a href="#" class="del">🗑️ Delete</a>
</div>
</td>
</tr>
<tr>
<td>Amy Lee</td>
<td>[email protected]</td>
<td>Active</td>
<td class="action-cell">
<button class="action-btn">⋯</button>
<div class="action-dropdown">
<a href="#">✏️ Edit</a>
<a href="#">👁️ View</a>
<a href="#">📋 Duplikat</a>
<a href="#">📤 Ekspor</a>
<div style="height:1px;background:#e2e8f0;margin:4px 0;"></div>
<a href="#" class="del">🗑️ Delete</a>
</div>
</td>
</tr>
<tr>
<td>Mike Williams</td>
<td>[email protected]</td>
<td>Pending</td>
<td class="action-cell">
<button class="action-btn">⋯</button>
<div class="action-dropdown">
<a href="#">✏️ Edit</a>
<a href="#">👁️ View</a>
<a href="#">📋 Duplikat</a>
<a href="#">📤 Ekspor</a>
<div style="height:1px;background:#e2e8f0;margin:4px 0;"></div>
<a href="#" class="del">🗑️ Delete</a>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
2. Filter Dropdown
<!DOCTYPE html>
<html lang="en">
<head>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
.filter-bar {
display: flex;
gap: 12px;
padding: 20px;
flex-wrap: wrap;
}
.filter-dropdown {
position: relative;
}
.filter-trigger {
padding: 10px 16px;
background: white;
border: 2px solid #e2e8f0;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
display: flex;
align-items: center;
gap: 8px;
transition: border-color 0.3s;
}
.filter-trigger:hover {
border-color: #667eea;
}
.filter-trigger::after {
content: '▾';
font-size: 10px;
color: #94a3b8;
}
.filter-dropdown .filter-menu {
position: absolute;
top: calc(100% + 6px);
left: 0;
background: white;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.12);
min-width: 200px;
padding: 8px;
opacity: 0;
visibility: hidden;
transform: translateY(-8px);
transition: all 0.2s;
z-index: 50;
}
.filter-dropdown:hover .filter-menu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.filter-option {
display: flex;
align-items: center;
gap: 10px;
padding: 9px 12px;
border-radius: 6px;
cursor: pointer;
transition: background 0.2s;
font-size: 14px;
}
.filter-option:hover {
background: #f1f5f9;
}
.filter-option input[type="checkbox"] {
accent-color: #667eea;
}
.active-filter {
background: #eef2ff;
border-color: #667eea;
color: #667eea;
}
.active-count {
background: #667eea;
color: white;
font-size: 11px;
padding: 1px 7px;
border-radius: 10px;
font-weight: bold;
}
</style>
</head>
<body>
<div class="filter-bar">
<div class="filter-dropdown">
<div class="filter-trigger active-filter">
Kategori <span class="active-count">2</span>
</div>
<div class="filter-menu">
<label class="filter-option">
<input type="checkbox" checked> Technology
</label>
<label class="filter-option">
<input type="checkbox" checked> Desain
</label>
<label class="filter-option">
<input type="checkbox"> Bisnis
</label>
<label class="filter-option">
<input type="checkbox"> Marketing
</label>
<label class="filter-option">
<input type="checkbox"> Photos & Videos
</label>
</div>
</div>
<div class="filter-dropdown">
<div class="filter-trigger">Price</div>
<div class="filter-menu">
<label class="filter-option">
<input type="checkbox"> Gratis
</label>
<label class="filter-option">
<input type="checkbox"> $0 - $100
</label>
<label class="filter-option">
<input type="checkbox"> $100 - $500
</label>
<label class="filter-option">
<input type="checkbox"> $500+
</label>
</div>
</div>
<div class="filter-dropdown">
<div class="filter-trigger">Rating</div>
<div class="filter-menu">
<label class="filter-option">
<input type="checkbox"> ⭐⭐⭐⭐⭐
</label>
<label class="filter-option">
<input type="checkbox"> ⭐⭐⭐⭐+
</label>
<label class="filter-option">
<input type="checkbox"> ⭐⭐⭐+
</label>
</div>
</div>
</div>
</body>
</html>
Conclusion
CSS Dropdowns lets you create interactive menus without JavaScript. Key points:
- Hide with
opacity: 0+visibility: hidden(notdisplay: none) position: absolute— The dropdown floats above the other contentz-index— Make sure the dropdown sits above overlapping content:focus-within— Important for keyboard accessibilitytransition— Smooth animation effects for good UX- Arrow indicator — A small arrow on the trigger signals that a dropdown exists
For more complex dropdowns (with keyboard navigation, focus trapping, etc.), consider using a library or vanilla JavaScript.