• Dropdown

    A menu of actions anchored to a trigger, built with the native popover API and a <menu>.

    Default

    <button popovertarget="my-dropdown">Actions</button>
    
    <div id="my-dropdown" popover>
      <menu>
        <li><button class="ghost">Edit</button></li>
        <li><button class="ghost">Duplicate</button></li>
        <li><button class="ghost">Share</button></li>
        <li><button class="ghost">Archive</button></li>
      </menu>
    </div>

    With separator

    Use an <hr> inside a <li> to visually group actions.

    <button popovertarget="my-dropdown">Actions</button>
    
    <div id="my-dropdown" popover>
      <menu>
        <li><button class="ghost">Edit</button></li>
        <li><button class="ghost">Duplicate</button></li>
        <li><button class="ghost">Share</button></li>
        <li><hr /></li>
        <li><button class="ghost destructive">Delete</button></li>
      </menu>
    </div>

    With section labels

    A <li> whose only child is a text-only <small> is automatically styled as a section label. No extra class needed.

    <div id="my-dropdown" popover>
      <menu>
        <li><small>Actions</small></li>
        <li><button class="ghost">New File</button></li>
        <li><button class="ghost">New Folder</button></li>
        <li><hr /></li>
        <li><small>Danger zone</small></li>
        <li><button class="ghost destructive">Delete</button></li>
      </menu>
    </div>

    With radios

    Radio inputs work naturally inside a dropdown — the checked state is preserved between opens and a checkmark appears via CSS. The popover stays open so the user can see their selection before dismissing.

    <button popovertarget="my-dropdown">Sort by</button>
    
    <div id="my-dropdown" popover>
      <menu>
        <li>
          <label>
            <input type="radio" name="sort" value="newest" checked /> Newest
          </label>
        </li>
        <li>
          <label> <input type="radio" name="sort" value="oldest" /> Oldest </label>
        </li>
        <li>
          <label> <input type="radio" name="sort" value="name" /> Name </label>
        </li>
        <li>
          <label> <input type="radio" name="sort" value="size" /> Size </label>
        </li>
      </menu>
    </div>

    With checkboxes

    Checkboxes allow multiple selections. An empty square indicates each item is toggleable; a filled square with checkmark appears when selected.

    <button popovertarget="my-dropdown">Columns</button>
    
    <div id="my-dropdown" popover>
      <menu>
        <li>
          <label>
            <input type="checkbox" name="col" value="name" checked /> Name
          </label>
        </li>
        <li>
          <label>
            <input type="checkbox" name="col" value="size" checked /> Size
          </label>
        </li>
        <li>
          <label> <input type="checkbox" name="col" value="type" /> Type </label>
        </li>
        <li>
          <label>
            <input type="checkbox" name="col" value="modified" /> Modified
          </label>
        </li>
      </menu>
    </div>

    Custom select

    Use radio inputs inside <label>s to build a styled select. A checkmark appears on the chosen option via CSS. A small script updates the trigger text and closes the dropdown on pick.

  • <button
      popovertarget="my-select"
      style="min-width: 10rem; justify-content: space-between"
    >
      <span>Choose a fruit</span>
      <svg><!-- chevron --></svg>
    </button>
    
    <div
      id="my-select"
      popover
      onchange="
        document.querySelector(`[popovertarget=${this.id}] span`).textContent =
          event.target.closest('label').textContent;
        this.hidePopover();
      "
    >
      <menu>
        <li>
          <label> <input type="radio" name="fruit" /> Apple </label>
        </li>
        <li>
          <label> <input type="radio" name="fruit" /> Banana </label>
        </li>
        <li>
          <label> <input type="radio" name="fruit" /> Cherry </label>
        </li>
      </menu>
    </div>

    In a form

    Wrap the trigger and popover in a <form> to participate in form submission. The change event bubbles up so you can handle it on the form.

  • <form onchange="alert('Selected: ' + event.target.value)">
      <button
        type="button"
        popovertarget="my-select"
        style="min-width: 10rem; justify-content: space-between"
      >
        <span>Choose a color</span>
        <svg><!-- chevron --></svg>
      </button>
      <div
        id="my-select"
        popover
        onchange="
          document.querySelector(`[popovertarget=${this.id}] span`).textContent =
            event.target.closest('label').textContent;
          this.hidePopover();
        "
      >
        <menu>
          <li>
            <label> <input type="radio" name="color" value="red" /> Red </label>
          </li>
          <li>
            <label> <input type="radio" name="color" value="green" /> Green </label>
          </li>
          <li>
            <label> <input type="radio" name="color" value="blue" /> Blue </label>
          </li>
        </menu>
      </div>
    </form>

    Search 5021 icons

    Type a name to find icons from the Tabler icon set.