Episode 8 of 12
Creating Nested Menu's with Flexbox
Build dropdown sub-menus within a Flexbox navigation — nested flex containers and hover-triggered dropdowns.
Creating Nested Menu's with Flexbox
Let's extend our Flexbox navbar to include dropdown sub-menus — menus that appear when hovering over a link. This uses nested flex containers and CSS positioning.
Updated HTML
<nav class="navbar">
<div class="nav-logo"><a href="#">DevBlog</a></div>
<ul class="nav-links">
<li><a href="#">Home</a></li>
<li class="has-submenu">
<a href="#">Services ▾</a>
<ul class="submenu">
<li><a href="#">Web Design</a></li>
<li><a href="#">Development</a></li>
<li><a href="#">SEO</a></li>
<li><a href="#">Consulting</a></li>
</ul>
</li>
<li class="has-submenu">
<a href="#">Blog ▾</a>
<ul class="submenu">
<li><a href="#">HTML & CSS</a></li>
<li><a href="#">JavaScript</a></li>
<li><a href="#">React</a></li>
</ul>
</li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
Parent Item Positioning
.has-submenu {
position: relative; /* Anchor point for the dropdown */
}
The Submenu (Hidden by Default)
.submenu {
position: absolute;
top: 100%; /* Below the parent link */
left: 0;
min-width: 200px;
background: #34495e;
border-radius: 0 0 8px 8px;
box-shadow: 0 8px 24px rgba(0,0,0,0.2);
list-style: none;
padding: 8px 0;
/* Hidden state */
opacity: 0;
visibility: hidden;
transform: translateY(-10px);
transition: opacity 0.25s ease,
visibility 0.25s ease,
transform 0.25s ease;
}
/* Show on hover */
.has-submenu:hover .submenu {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
Submenu Link Styling
.submenu li a {
display: block;
padding: 10px 20px;
color: #bbb;
text-decoration: none;
font-size: 14px;
transition: background 0.2s ease, color 0.2s ease, padding-left 0.2s ease;
}
.submenu li a:hover {
background: rgba(255,255,255,0.08);
color: #fff;
padding-left: 24px; /* Subtle indent on hover */
}
Adding a Separator Line
.submenu li + li {
border-top: 1px solid rgba(255,255,255,0.06);
}
Visual Arrow Indicator
.has-submenu > a::after {
content: '';
display: inline-block;
width: 0;
height: 0;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 5px solid currentColor;
margin-left: 6px;
vertical-align: middle;
transition: transform 0.2s ease;
}
.has-submenu:hover > a::after {
transform: rotate(180deg);
}
This creates a small triangle arrow using CSS borders that flips on hover.
The Flexbox Layout Stack
Navbar (flex container, row)
├── Logo (flex item)
├── Nav Links (flex item → also flex container, row)
│ ├── Home (flex item)
│ ├── Services (flex item, has-submenu)
│ │ └── Submenu (absolute positioned, vertical list)
│ │ ├── Web Design
│ │ ├── Development
│ │ └── SEO
│ ├── Blog (flex item, has-submenu)
│ │ └── Submenu (absolute positioned, vertical list)
│ ├── About (flex item)
│ └── Contact (flex item)
└── Actions (flex item → also flex container)
Why Flexbox + Position Works
| Technique | Handles |
|---|---|
| Flexbox | Horizontal layout of navbar and link items |
| position: absolute | Dropdown positioning below the parent item |
| opacity + visibility + transform | Smooth animated show/hide |
Preventing Dropdown Closing Gap
If there's a gap between the parent link and the dropdown, the mouse leaves the hover zone and the dropdown closes. Fix this by ensuring no gap:
.submenu {
top: 100%; /* No gap between parent and dropdown */
padding-top: 0;
}
/* Or add an invisible bridge */
.has-submenu::after {
content: '';
position: absolute;
top: 100%;
left: 0;
width: 100%;
height: 10px; /* Invisible hover bridge */
}
Key Takeaways
- Nested menus combine Flexbox (horizontal layout) with absolute positioning (dropdown)
position: relativeon the parent anchors the absolute dropdown below it- Use
opacity+visibility+transformfor smooth animated dropdowns - CSS-only hover dropdowns don't need JavaScript
- Prevent hover gaps between the trigger and the dropdown to avoid flicker