CSS Dropdowns
Navigation bars laid links in a row. A dropdown adds a nested panel that opens under a trigger — usually on hover, and better also when keyboard focus moves inside. Master one calm CSS pattern before inventing giant mega-menus.
A dropdown toolkit
📊 Dropdowns at a glance
| Piece | Everyday job |
|---|---|
| Relative trigger | Parent li (or wrapper) becomes the positioning anchor |
| Absolute panel | Nested menu sits under the trigger (top: 100%) |
| Hidden by default | display: none or off-screen until opened |
:hover reveal |
Pointer opens the panel |
:focus-within |
Keyboard users can open/keep the panel while tabbing |
z-index |
Keeps the open panel above following page content |
CSS-only dropdowns are a teaching classic. Real products often add JS for click-toggling on touch, escape-to-close, and richer accessibility — learn the CSS skeleton here first.
Relative trigger, nested list
Keep the trigger link in the top bar and nest a second list for the submenu. The parent item must be positioned so absolute children know their home.
.nav > li {
position: relative;
}
.nav > li > a {
display: inline-block;
padding: 0.5rem 0.75rem;
}
Absolute panel under the trigger
Place the submenu with position: absolute, pin it to the bottom of the trigger, and give it a solid background so page text does not bleed through.
.nav .submenu {
position: absolute;
top: 100%;
left: 0;
min-width: 12rem;
margin: 0;
padding: 0.35rem 0;
list-style: none;
background: #fff;
border: 1px solid #e5e5e5;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.08);
}
Hide until opened
Default the panel to closed. Opening everything at once defeats the dropdown.
.nav .submenu {
display: none;
}
Reveal on hover
When the pointer rests on the parent item, show the panel. Padding on the trigger helps avoid accidental closes at the edge.
.nav > li:hover > .submenu {
display: block;
}
Prefer focus-within too
Hover alone fails keyboard users. :focus-within keeps the panel open while focus is inside the item — a calmer CSS upgrade.
.nav > li:hover > .submenu,
.nav > li:focus-within > .submenu {
display: block;
}
A calm dropdown habit
Relative parent, absolute panel, hidden by default, hover + focus-within, modest z-index. Leave click-toggle mega-menus and complex ARIA wiring for richer patterns later — do not confuse this with the flat Navigation Bars lesson.
.nav .submenu {
z-index: 20;
}
.nav .submenu a {
display: block;
padding: 0.45rem 0.9rem;
text-decoration: none;
color: inherit;
}
Try it yourself
- Make each top-level
liposition: relative. - Nest a
.submenulist and position itabsolute; top: 100%; left: 0. - Hide with
display: none, then show onli:hover. - Add
:focus-withinso keyboard focus also opens the panel. - Raise
z-indexand write when you would add JS for touch click-toggle.
Common mistakes
- Absolute submenu without a relative parent (panel jumps away)
- Leaving the submenu visible by default
- Removing focus styles so keyboard users get lost
- Building a full JS mega-menu before learning this CSS skeleton
- Treating dropdowns as the whole page layout lesson
Summary
- Dropdowns nest a panel under a relative trigger
- Absolute +
top: 100%pins the menu below the link - Hide by default; reveal with hover and focus-within
- Use z-index so the panel covers page content
- Flat nav bars came first; nested menus are this lesson
🧠 Test Your Knowledge
Test Your Knowledge
Challenge yourself with this interactive quiz and see how well you understand the topic
📝 Instructions
- Read each question carefully
- Select the best answer for each question
- You can retake the quiz as many times as you want
- Your progress will be shown at the top