Search code examples
htmlpopover

Use popover api with `<div role="button">` as invoking element


When using the popover api I would like to open a popover with <div role="button"> but this doesn't seem to work. Here is a snippet that attempts this.

<div role="button" popovertarget="mypopover" style="border: 1px solid black; cursor: pointer;">Broken toggle</div>
<button popovertarget="mypopover">Happy toggle</button>

<div id="mypopover" popover>Popover content</div>

It only seems to work if a <button> is the invoking element.

Does someone know if the invoking element can be something else then a <button>?


Solution

  • Choosing which tag to use in HTML isn't just a question of semantics. Many elements also have built-in behaviour, which is also exposed on the element in JavaScript. Though it's possible to have some control of the semantics of an element through attributes like role, this doesn't change their actual behaviour.

    In the case of the Popover API, there is a limitation that only <button> and <input> elements are able to have a popovertarget attribute. MDN's page on the Popover API documents this.

    As usual, it's possible to author HTML with invalid tags, but the browser will just ignore these. Similar to if you try to put an href attribute on a <p> tag, it won't turn into a link.

    You should think very carefully and very deliberately when using role to change the semantics of an element instead of just using an appropriate element in the first place. In this example of using a <div> where you should use a <button>, you lose several pieces of functionality that are built into buttons such as being able to receive keyboard focus, and treating certain key presses as "click" events. These are very important accessibility features for people who use a keyboard instead of a pointer device like a mouse, for example because they may be blind or have a motor disability.

    It's possible to replicate these through methods such as giving the element tabindex="0" and adding event listeners to handle those keyboard events, but it's much easier to just use a <button>. If the problem is just one of styling, which in my experience is often the case when people avoid using a <button> element for something that really should use one, it's best to resolve that through CSS.

    If this is the case for you too, then you may be interested to learn about the unset CSS property, which is supported by all modern browsers now and can make it much easier to apply "clean slate" styling to a button.