Back

A Quick Guide to the Invoker Commands API

A Quick Guide to the Invoker Commands API

If you’ve ever wired up a button to open a <dialog> element, you know the drill: query the element, attach a click listener, call showModal(). It works, but it’s boilerplate you write over and over. The Invoker Commands API changes that by letting you declare that relationship directly in HTML — no JavaScript required for the most common cases.

As of late 2025, the Invoker Commands API has reached Baseline availability across Chrome/Edge, Firefox, and Safari, making it a practical choice for modern projects. You can check the current browser support on webstatus.dev or caniuse.com.

Key Takeaways

  • The Invoker Commands API lets you control dialogs and popovers declaratively using commandfor and command attributes on <button> elements — no JavaScript needed for built-in commands.
  • Built-in commands like show-modal, close, request-close, and popover toggles handle top-layer placement, focus management, and accessibility automatically.
  • Custom commands (prefixed with --) let you define your own behaviors while keeping a clean, declarative wiring pattern in your HTML.
  • Always set type="button" on invoker buttons to prevent form-submission defaults from interfering with the command attribute.

What Are the command and commandfor Attributes?

The Invoker Commands API introduces two HTML attributes on <button> elements:

  • commandfor — the id of the target element you want to control
  • command — the action to perform on that target when the button is activated

Together, they form a declarative link between an invoking button and its target. When the button is clicked, pressed via keyboard, or otherwise activated, the browser dispatches a CommandEvent on the target element and — for built-in commands — executes the corresponding behavior automatically.

Important: Always add type="button" to any button using these attributes. Without it, buttons inside forms default to type="submit", which causes unexpected behavior.

Controlling Dialogs and Popovers with HTML

This is where the API delivers the most immediate value. Previously, controlling a <dialog> element required JavaScript. Now you can do it declaratively:

<button type="button" commandfor="my-dialog" command="show-modal">
  Open Dialog
</button>

<dialog id="my-dialog">
  <p>Hello from the dialog!</p>
  <button type="button" commandfor="my-dialog" command="request-close">
    Close
  </button>
</dialog>

No JavaScript. The browser handles top-layer placement, focus trapping, and focus restoration when the dialog closes.

Built-in Commands Reference

Target Elementcommand ValueBehavior
<dialog>show-modalOpens as a modal dialog
<dialog>closeCloses the dialog immediately
<dialog>request-closeRequests close (respects cancel event)
[popover]toggle-popoverToggles popover open/closed
[popover]show-popoverShows the popover
[popover]hide-popoverHides the popover

For popovers, this serves a similar purpose to the older popovertarget attribute. The Invoker Commands API is a more general mechanism for declarative UI actions, but the original popover attributes still exist and remain supported. See the MDN guide to the Popover API for details.

Accessibility Is Built In

For built-in commands, the browser automatically handles key accessibility and interaction behaviors. Dialog commands integrate with the browser’s native <dialog> handling, including top-layer behavior and focus restoration when the dialog closes. These platform-level behaviors help ensure consistent interaction patterns and better accessibility without requiring extra ARIA attributes.

Custom Commands Still Need JavaScript

The API also supports custom commands for your own components. Any command value starting with -- is treated as a custom command. The browser dispatches a CommandEvent on the target, and your JavaScript handles the rest:

<button type="button" commandfor="color-box" command="--toggle-highlight">
  Highlight
</button>
<div id="color-box"></div>

<script>
  document.getElementById('color-box').addEventListener('command', (e) => {
    if (e.command === '--toggle-highlight') {
      e.target.classList.toggle('highlighted');
    }
  });
</script>

The -- prefix is a reserved namespace — browsers guarantee they will never use it for built-in commands, so it’s safe for custom use. The CommandEvent exposes both e.command (the command string) and e.source (the button that triggered it), giving you everything you need to act on the event.

Conclusion

The Invoker Commands API makes declarative UI control in HTML a reality for the most common patterns. Use built-in commands for dialogs and popovers to get accessibility, focus management, and zero JavaScript for free. Use custom -- commands when you need JavaScript behavior but want a cleaner, more declarative wiring pattern. It’s a small API with a clear scope — and that’s exactly what makes it useful.

FAQs

Currently, the commandfor and command attributes are only supported on button elements. Other interactive elements like links or inputs cannot act as invokers using this API. If you need a non-button element to trigger a command, you will still need JavaScript event handling for that interaction.

If the commandfor value does not match any element id in the document, the button activation simply does nothing. No error is thrown and no CommandEvent is dispatched. Make sure the id in commandfor exactly matches the target element id, including case sensitivity.

No. The CommandEvent dispatched by custom commands does not bubble through the DOM tree. You must listen for the event on the target element itself rather than relying on event delegation.

The Invoker Commands API provides a more general mechanism for declarative UI actions than the earlier popovertarget attributes. While both approaches currently work, commandfor and command can be used for dialogs, popovers, and custom commands, making them the more flexible option for modern HTML interfaces.

Complete picture for complete understanding

Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.

Check our GitHub repo and join the thousands of developers in our community.

OpenReplay