About this snippet

An account button opens a dropdown menu beneath it. Clicking the button toggles the menu, clicking anywhere else or pressing Escape closes it, and the whole thing is two attributes and some CSS.

The menu is a popover, so the browser puts it in the top layer and handles open, close and light dismiss through the popovertarget attribute on the button. Anchor positioning ties it back to the button. The button declares an anchor-name, the menu points at it with position-anchor, and position-area drops it into the slot below, right aligned. The fade and slide are a transition on the :popover-open state, with @starting-style supplying the values it animates from.

Popover and anchor positioning are both in every current browser. In an older browser without anchor positioning the @supports fallback centers the menu as a small floating panel, so the control stays usable.

Size
3.1 KB
Uses
HTML, CSS
Loads
Nothing external
Views
41
<header class="bar">
  <span class="brand">Console</span>
  <button type="button" class="menu-btn" id="menu-btn" popovertarget="account-menu">
    <span class="avatar">JD</span>
    <span>Jordan</span>
    <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"></path></svg>
  </button>
  <div class="menu" id="account-menu" popover>
    <a href="#" class="menu-item">Profile</a>
    <a href="#" class="menu-item">Billing</a>
    <a href="#" class="menu-item">Team settings</a>
    <hr>
    <a href="#" class="menu-item danger">Sign out</a>
  </div>
</header>
<main class="page">
  <h1>Popover plus anchor positioning</h1>
  <p>Open the account menu, then click anywhere on the page or press Escape to close it.</p>
</main>
*, *::before, *::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  margin: 0;
  background: #f8fafc;
  color: #0f172a;
  min-height: 100vh;
}

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 64px;
  padding: 0 24px;
  background: #ffffff;
  border-bottom: 1px solid #e2e8f0;
}

.brand {
  font-weight: 700;
  letter-spacing: -0.01em;
}

.menu-btn {
  anchor-name: --account;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: inherit;
  font-weight: 500;
  color: #0f172a;
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 999px;
  padding: 6px 12px 6px 6px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.menu-btn:hover {
  background: #f1f5f9;
}

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: #1d4ed8;
  color: #ffffff;
  font-size: 0.75rem;
  font-weight: 700;
}

.menu {
  position-anchor: --account;
  position-area: block-end span-inline-start;
  position-try-fallbacks: flip-block;
  margin: 8px 0 0;
  inset: auto;
  min-width: 200px;
  padding: 6px;
  background: #ffffff;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  box-shadow: 0 16px 32px -12px rgba(15, 23, 42, 0.3);
  opacity: 0;
  translate: 0 -6px;
  transition: opacity 0.16s ease, translate 0.16s ease, overlay 0.16s allow-discrete, display 0.16s allow-discrete;
}

.menu:popover-open {
  opacity: 1;
  translate: 0 0;
}

@starting-style {
  .menu:popover-open {
    opacity: 0;
    translate: 0 -6px;
  }
}

.menu hr {
  border: 0;
  border-top: 1px solid #e2e8f0;
  margin: 6px 0;
}

.menu-item {
  display: block;
  padding: 9px 12px;
  border-radius: 8px;
  color: #0f172a;
  text-decoration: none;
  font-size: 0.9375rem;
}

.menu-item:hover {
  background: #f1f5f9;
}

.menu-item.danger {
  color: #dc2626;
}

.menu-item.danger:hover {
  background: #fef2f2;
}

.page {
  max-width: 560px;
  margin: 60px auto;
  padding: 0 24px;
}

.page h1 {
  font-size: 1.75rem;
  margin: 0 0 12px;
}

.page p {
  margin: 0;
  color: #475569;
  line-height: 1.6;
}

@supports not (position-anchor: --account) {
  .menu {
    position: fixed;
    inset: 50% auto auto 50%;
    transform: translate(-50%, -50%);
    margin: 0;
  }
}
Esc
↑↓ moveEnter select

Start from a template

Open an .html file, or HTML, CSS, JS, Markdown, Less or TypeScript files. You can also drop them here. Styles and scripts go into their panes.

Share

Source

Keyboard shortcuts

Save