ComponentsDropdown

A menu from details.dropdown, or from the native popover attribute with anchor positioning.

On this page

There are two ways to build a dropdown. details.dropdown is the Pico CSS v2.1.1 pattern: no script, and it works in every browser of the floor. The popover version is newer. It uses a button and a popover list, and places itself next to the button with anchor positioning.

details.dropdown

Give a <details> the class dropdown, a <summary> for the label and a <ul> right after it for the items. By default the summary looks like a select.

Dropdown
<details class="dropdown">
  <summary>Dropdown</summary>
  <ul>
    <li><a href="#">Solid</a></li>
    <li><a href="#">Liquid</a></li>
    <li><a href="#" aria-current="true">Gas</a></li>
    <li><a href="#">Plasma</a></li>
  </ul>
</details>

An invisible layer covers the page while the menu is open, so a click outside closes it. The item with aria-current gets the hover background.

Checkboxes and radios

Put a <label> with an input in each <li> to build a multiple choice menu. The whole row highlights on hover.

Dropdown with checkboxes
<details class="dropdown">
  <summary>Select fruits</summary>
  <ul>
    <li>
      <label><input type="checkbox" name="apple" /> Apple</label>
    </li>
    <li>
      <label><input type="checkbox" name="banana" checked /> Banana</label>
    </li>
    <li>
      <label><input type="checkbox" name="cherry" /> Cherry</label>
    </li>
  </ul>
</details>

Button style

Add role="button" to the summary for a button look. The usual secondary, contrast and outline classes work.

Dropdown as a button
<details class="dropdown">
  <summary role="button" class="outline secondary">Menu</summary>
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</details>

Validation state

The select-style summary reads aria-invalid like a form field: false gives the valid colors and true the invalid ones.

Dropdown validation
<details class="dropdown">
  <summary aria-invalid="true">Pick one</summary>
  <ul>
    <li><a href="#">Option</a></li>
  </ul>
</details>

In a nav

Inside a nav the dropdown sits inline with the links and the summary takes the link padding. Put it in an <li>. For a menu that opens toward the left edge, set dir="rtl" on the <ul> itself. An ancestor with dir is not enough.

Dropdown in a nav
<nav>
  <ul>
    <li><strong>Acme</strong></li>
  </ul>
  <ul>
    <li><a href="#">Features</a></li>
    <li>
      <details class="dropdown">
        <summary>Account</summary>
        <ul dir="rtl">
          <li><a href="#">Profile</a></li>
          <li><a href="#">Settings</a></li>
          <li><a href="#">Sign out</a></li>
        </ul>
      </details>
    </li>
  </ul>
</nav>

Popover menu

A <button> with popovertarget and a <ul popover> (or <menu popover>) with a matching id. The browser handles open, close, Escape and light dismiss. The list drops below the button and flips to the other side when there is no room. No script and no class.

Popover menu
<button popovertarget="menu">Actions</button>
<ul popover id="menu">
  <li><a href="#edit">Edit</a></li>
  <li><a href="#duplicate" aria-current="page">Duplicate</a></li>
  <li><a href="#archive">Archive</a></li>
</ul>

This version also works in the class-less build, because it needs no class. The details.dropdown rules are not in the class-less files.

Where the browser does not support popover, the list shows as normal content. Where it does not support anchor positioning, the menu opens in the top layer with fixed placement. See Popover patterns for placement and fallbacks.

Accessibility

For details.dropdown, the summary is focusable and toggles with Enter or Space, and the links inside are normal tab stops. A list of links is navigation, so no role="menu" is needed. The popover version leaves open state and dismissal to the browser. Use aria-current on the item that matches the current page.

Customization

--pico-dropdown-background-color
light-dark(#ffffff, #1c1e22)
Menu surface.
--pico-dropdown-border-color
light-dark(#e3e4e8, #313337)
Menu border.
--pico-dropdown-box-shadow
0 0 0 0.0625rem oklch(0.2 0.02 265 / 0.07), 0 0.125rem 0.25rem -0.0625rem oklch(0.2 0.02 265 / 0.06), 0 0.75rem 2rem -0.5rem oklch(0.2 0.02 265 / 0.18)
Menu shadow: a 1px ring and two drops, deeper than the card shadow.
--pico-card-border-radius
calc(var(--pico-border-radius) * 1.5)
Corner radius of the menu. Items use three quarters of --pico-border-radius.
--pico-dropdown-color
var(--pico-color)
Item text color.
--pico-dropdown-hover-background-color
light-dark(#f2f3f6, #292b2f)
Background of the hovered, focused or current item.
--pico-icon-chevron
SVG data URI
The arrow in the summary.