How to make a dropdown menu
Short answer
details opens and closes by itself, and the list goes under the button with position: absolute:
<style>
.dd { position: relative; display: inline-block; }
.dd summary { list-style: none; cursor: pointer; padding: 6px 12px; background: royalblue; color: white; border-radius: 6px; }
.dd ul { position: absolute; top: 100%; left: 0; z-index: 1; margin: 4px 0 0; padding: 6px 0; list-style: none; min-width: 140px; background: white; border: 1px solid gainsboro; border-radius: 6px; box-shadow: 0 6px 16px rgb(0 0 0 / 15%); }
.dd a { display: block; padding: 6px 12px; color: inherit; text-decoration: none; }
.dd a:hover { background: aliceblue; }
</style>
<details class="dd">
<summary>Account ▾</summary>
<ul><li><a href="https://example.com">Profile</a></li><li><a href="https://example.com">Orders</a></li><li><a href="https://example.com">Log out</a></li></ul>
</details>
<p>Content below the menu</p>A popover menu
The popover attribute puts the menu in the top layer above everything, and closes it on an outside click and on Esc. A button connects to it with popovertarget:
<button popovertarget="menu">Sort by ▾</button>
<div id="menu" popover style="padding: 8px; border: 1px solid gainsboro; border-radius: 6px;">
<p style="margin: 4px;">Price</p><p style="margin: 4px;">Rating</p><p style="margin: 4px;">Newest</p>
</div>By default a popover sits in the middle of the screen. Anchor positioning (position-anchor) ties it to the button, and where that is not supported, a small script does.
Common mistake
A hover-only menu: phones have no hover, and the keyboard cannot open it. If the menu does open on hover, add :focus-within so Tab opens it too.
Functions used in this recipe
- <details>, <summary> — A disclosure block without JavaScript: `<summary>` is the visible title, the rest is hidden until clicked.
- position — How an element is positioned: in the normal flow or by offsets.
- :has() — Matches an element that contains something matching the selector in brackets — the "parent selector".
- popover — Turns an element into a layer that pops up over the page — without JavaScript.