How to Make a Dropdown Menu in HTML & CSS
To make a dropdown menu, nest a second list of links inside a menu item, hide it with CSS, and show it when the item is opened. Give the parent position: relative and the dropdown position: absolute; top: 100% so it appears underneath. Use a button that opens it on click, so it works with touch screens and keyboards too.
Last updated: October 4, 2026
Quick answer
Two kinds of “dropdown”
The word means two different things in HTML, so first check which one you need:
- A navigation dropdown: a menu item (like “Services”) that opens a list of links. You build it from lists, links and CSS. Most of this tutorial covers this kind.
- A form dropdown: a field where the visitor picks one option, built with
<select>. It’s covered at the end of this page.
Step 1: Nest a list inside a menu item
A dropdown is a list inside a list. The outer list is the main menu; one of its items contains a second <ul> with the sub-links:
- Start with a normal navigation menu:
<nav>with a<ul>of links. - Pick the item that should open a dropdown, give it a class such as
dropdown, and put a second<ul>inside it after the item’s label. - Fill the inner list with
<li><a href>links.
Before any CSS, the sub-links simply appear indented under their parent, which is a perfectly usable fallback.
Step 2: A simple CSS hover dropdown
The quickest version uses only CSS:
- Give the parent item
position: relative. It becomes the anchor the dropdown is positioned against. - Give the inner list
position: absolute; top: 100%; left: 0;so it sits right underneath, on top of the page content. Add a background and amin-width. - Hide it with
display: none, and show it with.dropdown:hover .dropdown-menu { display: block; }. - Add
:focus-withinto the same rule, so it also opens when someone tabs to a link inside it with the keyboard.
Hover over “Services” in the preview.
This works with a mouse, but hover has two problems: touch screens have no hover (a tap on “Services” just follows its link), and the menu closes as soon as the pointer slips off it. Step 3 fixes both.
Step 3: An accessible click-to-open dropdown
The most reliable dropdown opens when its button is clicked or tapped, and tells assistive technology whether it’s open:
- Replace the parent link with a
<button>. Give itaria-expanded="false"andaria-controlsset to the dropdown list’sid. - In CSS, show the list only when the parent has an
openclass. - In JavaScript, toggle that class on click and update
aria-expandedtotrueorfalse. - Close the menu when the visitor clicks anywhere else or presses Escape.
Click “Services”, then click outside the menu or press Escape.
If the parent item should also be a page of its own (a “Services” overview page), keep a normal link for it and put a small separate button with an arrow next to it that opens the dropdown. Then a click on the text goes to the page, and the arrow opens the sub-menu.
Dropdowns inside a mobile menu
On phones, navigation usually collapses behind a ☰ button (see how to make a navigation bar). Inside that opened menu, there’s no room for a floating box, so the dropdown should open in place instead: in your mobile media query, change the dropdown from position: absolute to position: static, remove its shadow, and indent its links slightly. The sub-links then push the items below them down, like an accordion. Keep the same button and aria-expanded toggle, so one piece of JavaScript works on every screen size.
No-JavaScript option: <details> and <summary>
The <details> element opens and closes by itself when its <summary> is clicked, with no JavaScript at all, and it works with the keyboard out of the box. With a little positioning it makes a simple dropdown. The one thing it doesn’t do on its own is close when you click elsewhere on the page.
Form dropdowns with <select>
If you need a form field where the visitor chooses one option, don’t build a menu: use <select> with <option> elements. The browser draws it, it works on every device (phones show their own native picker), and its value is sent with the form. Group long lists with <optgroup>, and connect a <label> to it.
Which dropdown should I use?
| Approach | Works on touch | Keyboard | Best for |
|---|---|---|---|
CSS :hover | Poorly | With :focus-within | Quick prototypes, desktop-only sites |
| Button + JavaScript | Yes | Yes, with aria-expanded | Site navigation menus |
<details> / <summary> | Yes | Yes, built in | Simple menus without JavaScript |
<select> | Yes (native picker) | Yes, built in | Choosing a value in a form |
Common dropdown mistakes
- Hover only. Touch screen visitors can’t open it, and keyboard users can’t reach it. Use a button or add
:focus-within. - A gap between the item and the menu. If the pointer crosses empty space on the way down, a hover menu closes. Use
top: 100%with no margin. - Dropdown hidden behind other content. Add a
z-index, and check that no parent hasoverflow: hidden, which clips it. - Menus that run off the screen. For an item near the right edge, anchor the dropdown with
right: 0instead ofleft: 0. - Too many levels. Dropdowns inside dropdowns are hard to use, especially on phones. One level is usually enough.
- Building a fake select. For choosing a value in a form, the real
<select>is more accessible than any custom menu.