Menu
A dropdown on the Popover API. Also fully working on this JavaScript-free page: open one, click outside it, press Escape, open a second one and watch the first close.
Reference
sk-menu
The platform supplies light dismiss, Escape, the top layer, and closing other popovers in the same stack. Positioning uses the implicit anchor that a popovertarget invoker creates, so there is no anchor-name to declare and therefore no per-instance inline style for a strict CSP to reject.
<button class="sk-button" popovertarget="row-menu">Actions</button>
<div class="sk-menu" id="row-menu" popover>
<p class="sk-menu-label">Group</p>
<a class="sk-menu-item" href="/edit">Edit</a>
<hr class="sk-menu-separator">
<button class="sk-menu-item" data-status="danger"
popovertarget="row-menu" popovertargetaction="hide">Delete</button>
</div>| Attribute | Type | Default | Notes |
|---|---|---|---|
popover | boolean attribute | - | Puts the menu in the top layer and gives it light dismiss. |
popovertarget | menu id | - | On the trigger. Broadly supported - unlike the modal invoker, this needs no fallback. |
popovertargetaction | "hide" | "show" | "toggle" | "toggle" | "hide" on an item button dismisses the menu when it acts. |
data-align | "end" | start | Hangs from the trigger's trailing edge. |
data-side | "top" | bottom | Opens upward. It flips automatically when there is no room, so this is only for when you want it up by default. |
position-try-fallbacks | - | flip-block, flip-inline | Why a menu on the last row of a table does not open off the bottom of the screen. |
Examples
Actions
Items are buttons or links, never a div with a handler - both are focusable and operable from the keyboard with nothing added.
Show markup
<div class="sk-flex sk-items-center sk-gap-3">
<button class="sk-button" type="button" data-variant="neutral" data-size="md" popovertarget="demo-menu">
Actions
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</button>
<div class="sk-menu" id="demo-menu" popover aria-label="Actions">
<a class="sk-menu-item" href="#">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M12 5v14">
</path>
<path d="M5 12h14">
</path>
</svg>
Duplicate
</a>
<a class="sk-menu-item" href="#">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M14 4h6v6">
</path>
<path d="M20 4 11 13">
</path>
<path d="M18 14v4a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4">
</path>
</svg>
Open in a new tab
</a>
<hr class="sk-menu-separator">
<button type="button" class="sk-menu-item" data-status="danger" popovertarget="demo-menu" popovertargetaction="hide">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M4 7h16">
</path>
<path d="M10 11v6">
</path>
<path d="M14 11v6">
</path>
<path d="M5 7l1 12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2l1-12">
</path>
<path d="M9 7V5a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2">
</path>
</svg>
Delete
</button>
</div>
</div>Grouped
Labels and separators. The separator is an <hr>, so the split is in the document and not only in the paint.
Show markup
<div class="sk-flex sk-items-center sk-gap-3">
<button class="sk-button" type="button" data-variant="neutral" data-size="md" popovertarget="demo-menu-2">
View
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</button>
<div class="sk-menu" id="demo-menu-2" popover aria-label="View options">
<p class="sk-menu-label">
Sort by
</p>
<button type="button" class="sk-menu-item" popovertarget="demo-menu-2" popovertargetaction="hide">
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="M20 6 9 17l-5-5">
</path>
</svg>
Newest first
</button>
<button type="button" class="sk-menu-item" popovertarget="demo-menu-2" popovertargetaction="hide">
Oldest first
</button>
<hr class="sk-menu-separator">
<p class="sk-menu-label">
Density
</p>
<button type="button" class="sk-menu-item" popovertarget="demo-menu-2" popovertargetaction="hide">
Comfortable
<span class="sk-menu-item-detail">
⌘1
</span>
</button>
<button type="button" class="sk-menu-item" popovertarget="demo-menu-2" popovertargetaction="hide">
Compact
<span class="sk-menu-item-detail">
⌘2
</span>
</button>
<hr class="sk-menu-separator">
<button type="button" class="sk-menu-item" disabled>
Unavailable option
</button>
</div>
</div>Aligned to the end
Show markup
<div class="sk-flex sk-justify-between sk-items-center">
<span class="sink-caption">
the trigger is at the far edge
</span>
<button class="sk-button" type="button" data-variant="neutral" data-size="sm" popovertarget="demo-menu-3">
Options
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</button>
<div class="sk-menu" id="demo-menu-3" popover data-align="end" aria-label="Options">
<a class="sk-menu-item" href="#">
Rename
</a>
<a class="sk-menu-item" href="#">
Move
</a>
<a class="sk-menu-item" href="#">
Archive
</a>
</div>
</div>In a table
The reason position-try-fallbacks is there: open the menu on the last row and it flips above the trigger rather than off the bottom of the frame.
| Name | Actions |
|---|---|
| Ada Lovelace | |
| Grace Hopper | |
| Alan Turing | |
| Katherine Johnson | |
| Edsger Dijkstra |
Show markup
<div class="sk-table-wrap">
<table class="sk-table" data-density="compact" data-hoverable="true">
<thead>
<tr>
<th scope="col">
Name
</th>
<th scope="col" data-col="actions">
<span class="sk-visually-hidden">
Actions
</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Ada Lovelace
</td>
<td data-col="actions">
<button class="sk-button" type="button" data-variant="quiet" data-size="sm" popovertarget="row-menu-0">
Actions
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</button>
<div class="sk-menu" id="row-menu-0" popover data-align="end" aria-label="Actions for Ada Lovelace">
<a class="sk-menu-item" href="#">
Edit
</a>
<a class="sk-menu-item" href="#">
Duplicate
</a>
<hr class="sk-menu-separator">
<button type="button" class="sk-menu-item" data-status="danger" popovertarget="row-menu-0" popovertargetaction="hide">
Delete
</button>
</div>
</td>
</tr>
<tr>
<td>
Grace Hopper
</td>
<td data-col="actions">
<button class="sk-button" type="button" data-variant="quiet" data-size="sm" popovertarget="row-menu-1">
Actions
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</button>
<div class="sk-menu" id="row-menu-1" popover data-align="end" aria-label="Actions for Grace Hopper">
<a class="sk-menu-item" href="#">
Edit
</a>
<a class="sk-menu-item" href="#">
Duplicate
</a>
<hr class="sk-menu-separator">
<button type="button" class="sk-menu-item" data-status="danger" popovertarget="row-menu-1" popovertargetaction="hide">
Delete
</button>
</div>
</td>
</tr>
<tr>
<td>
Alan Turing
</td>
<td data-col="actions">
<button class="sk-button" type="button" data-variant="quiet" data-size="sm" popovertarget="row-menu-2">
Actions
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</button>
<div class="sk-menu" id="row-menu-2" popover data-align="end" aria-label="Actions for Alan Turing">
<a class="sk-menu-item" href="#">
Edit
</a>
<a class="sk-menu-item" href="#">
Duplicate
</a>
<hr class="sk-menu-separator">
<button type="button" class="sk-menu-item" data-status="danger" popovertarget="row-menu-2" popovertargetaction="hide">
Delete
</button>
</div>
</td>
</tr>
<tr>
<td>
Katherine Johnson
</td>
<td data-col="actions">
<button class="sk-button" type="button" data-variant="quiet" data-size="sm" popovertarget="row-menu-3">
Actions
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</button>
<div class="sk-menu" id="row-menu-3" popover data-align="end" aria-label="Actions for Katherine Johnson">
<a class="sk-menu-item" href="#">
Edit
</a>
<a class="sk-menu-item" href="#">
Duplicate
</a>
<hr class="sk-menu-separator">
<button type="button" class="sk-menu-item" data-status="danger" popovertarget="row-menu-3" popovertargetaction="hide">
Delete
</button>
</div>
</td>
</tr>
<tr>
<td>
Edsger Dijkstra
</td>
<td data-col="actions">
<button class="sk-button" type="button" data-variant="quiet" data-size="sm" popovertarget="row-menu-4">
Actions
<svg class="sk-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path d="m6 9 6 6 6-6">
</path>
</svg>
</button>
<div class="sk-menu" id="row-menu-4" popover data-align="end" aria-label="Actions for Edsger Dijkstra">
<a class="sk-menu-item" href="#">
Edit
</a>
<a class="sk-menu-item" href="#">
Duplicate
</a>
<hr class="sk-menu-separator">
<button type="button" class="sk-menu-item" data-status="danger" popovertarget="row-menu-4" popovertargetaction="hide">
Delete
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>