← Back to CSS Course | Chapter 6: Selectors & Styling | Lesson 9 of 22

CSS Advanced Dropdowns

A single-level hover dropdown is the easy case. Real navigation menus often need a submenu inside a submenu, or a menu that opens on click for touch devices where hover does not exist at all.

Nesting a Submenu Inside a Dropdown

A multi-level dropdown is built by placing another absolutely positioned list inside a dropdown item, hidden by default and shown when that specific item is hovered. Each nesting level needs its own position: relative parent so the inner submenu positions relative to the correct item, not the outer menu.

Example: Nesting a Submenu Inside a Dropdown

css
<style>
.item {
  position: relative;
  background: #eee;
  padding: 8px;
}
.submenu {
  display: none;
  position: absolute;
  background: lightyellow;
  border: 1px solid #ccc;
  padding: 8px;
}
.item:hover .submenu {
  display: block;
}
</style>
<div class="item">
  Tools
  <div class="submenu">Sub Item</div>
</div>

Click-Triggered Dropdowns Without JavaScript

Hover does not exist on touch devices, so click-triggered dropdowns are needed for mobile support. A pure-CSS trick uses a hidden checkbox paired with a label: clicking the label toggles the checkbox, and a sibling selector shows the menu when the checkbox is checked.

Example: Click-Triggered Dropdowns Without JavaScript

css
<style>
.menu {
  display: none;
  background: lightyellow;
  border: 1px solid #ccc;
  padding: 8px;
}
#toggle:checked ~ .menu {
  display: block;
}
</style>
<input type="checkbox" id="toggle" hidden>
<label for="toggle">Menu</label>
<div class="menu">Shown when the checkbox is checked</div>

Positioning Submenus That Overflow the Viewport

A submenu that always opens to the right can run off the edge of the screen on narrow viewports. A common fix is a modifier class, applied via a media query or JavaScript detection, that flips the submenu's position to open leftward instead.

Example: Positioning Submenus That Overflow the Viewport

css
<style>
.submenu {
  position: absolute;
  left: 100%;
  background: lightyellow;
  border: 1px solid #ccc;
  padding: 8px;
}
.submenu.flip {
  left: auto;
  right: 100%;
}
</style>
<div class="submenu flip">Opens leftward instead of running off-screen</div>

Animating the Submenu Reveal

Instead of an instant display: none to display: block toggle, animating opacity and a small translateY transform on the submenu creates a smoother, more polished fade-and-slide-down reveal, common in production navigation menus.

Example: Animating the Submenu Reveal

css
<style>
.item {
  position: relative;
  background: #eee;
  padding: 8px;
}
.submenu {
  background: lightyellow;
  border: 1px solid #ccc;
  padding: 8px;
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity 0.2s, transform 0.2s;
}
.item:hover .submenu {
  opacity: 1;
  transform: translateY(0);
}
</style>
<div class="item">
  Menu
  <div class="submenu">Fades and slides down</div>
</div>

Keyboard and Screen Reader Considerations for Nested Menus

Multi-level dropdowns built purely with :hover are unreachable by keyboard users, since Tab does not trigger hover states. Combining :focus-within with :hover on every nesting level, and using aria-haspopup/aria-expanded attributes maintained via JavaScript, makes nested menus properly accessible.

Example: Keyboard and Screen Reader Considerations for Nested Menus

css
<style>
.item {
  background: #eee;
  padding: 8px;
}
.submenu {
  display: none;
  background: lightyellow;
  border: 1px solid #ccc;
  padding: 8px;
}
.item:hover .submenu,
.item:focus-within .submenu {
  display: block;
}
</style>
<div class="item">
  <a href="#" aria-haspopup="true" aria-expanded="false">Menu</a>
  <div class="submenu"><a href="#">Item</a></div>
</div>

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.