The HTML command and commandfor attributes


command and commandfor are new attributes for the HTML <button> element. They provide a declarative way to open and close dialogs and popovers, without the need for JavaScript.

The command attribute specifies an action to be performed when the button is pressed. The possible values are:

CommandBehaviour
"show-modal"Show a modal <dialog>.
"close"Close a <dialog>.
"show-popover"Show a popover.
"hide-popover"Hide a popover.
"toggle-popover"Toggle a popover between showing and hidden.

Custom values can also be used, which I’ll cover later in this article. In the future more built-in commands may be available.

The naming of the commands reflects the equivalent JavaScript method. The show-modal command, for example, is a HTML equivalent of document.querySelector('dialog').showModal().

commandfor is used to specify the ID of the popover or dialog to be opened or closed or toggled.

<button command="show-modal" commandfor="dialog-1">Show modal dialog</button>

<dialog id="dialog-1">
<h2>This is a modal dialog</h2>
<button command="close" commandfor="dialog-1">Close</button>
</dialog>

This is a modal dialog

Prior to command and commandfor, there was no way to open a modal dialog without JavaScript. That was not the case for the popover API, which already had the popovertargetaction and popovertarget attributes, the functionality of which is duplicated by command and commandfor.

The following lines of code are equivalent:

<button popovertarget="popover1">Toggle popover 1</button>
<div id="popover1" popover>Popover 1</div>

<button command="toggle-popover" commandfor="popover2">Toggle popover 2</button>
<div id="popover2" popover>Popover 2</div>
Popover 1
Popover 2

Its nice to have a consistent approach shared between popovers and dialogs. For toggling a popover, however, using one attribute rather than two may be preferable. Toggling a popover is the default behaviour when only popovertarget is specified, whereas command and commandfor must both be specified.

The command event

The command event fires on the popover, dialog, or any other element with an ID referenced by commandfor. It does not fire on the button.

<button command="toggle-popover" commandfor="popover">Toggle popover</button>
<div 
oncommand="event.target.textContent = `The ${event.command} command was invoked`"
id="popover" 
popover>
Placeholder content...</div>

Popover content

Popovers and dialogs also have toggle and beforetoggle events, which fire whenever the element gets opened or closed — including via the escape key or light dismiss. The command event fires only when the associated button is pressed. The command event is primarily useful when working with custom commands.

command events are always non-bubbling.

Custom commands

Unlike the built-in predefined commands, custom commands rely on JavaScript. The name of a custom command must start with two hyphens e.g. command="--my-command".

<button commandfor="example" command="--multi-col-view" value=2>Multi-column: 2 columns</button>
<button commandfor="example" command="--multi-col-view" value=3>Multi-column: 3 columns</button>
<button commandfor="example" command="--grid-view" value=2>Grid: 2 columns</button>
<button commandfor="example" command="--grid-view" value=3>Grid: 3 columns</button>

The command event contains a source property that references the button that caused the event to fire. This can be used to access data- attributes or a value from the relevant button.

document.getElementById("example").addEventListener("command", (event) => {
    if (event.command === "--grid-view") {
        event.target.style.columnCount = "";
        event.target.style.display = "grid";
        event.target.style.gridTemplateColumns = `repeat(${event.source.value}, 1fr)`
    } else if (event.command === "--multi-col-view") {
        event.target.style.display = "";
        event.target.style.columnCount = event.source.value;
    }
});
Item 1
Item 2
Item 3
Item 4
Item 5
Item 6