Update 20.11.23 — the current behaviour of not being able to interact with a popover above a modal dialog is ‘as spec’ but could maybe be tweaked. I opened an issue at the CSS Working Group issues here, so add your thoughts: https://github.com/whatwg/html/issues/9936#issuecomment-1818385368

Imagine an interface. In it, there is a button. You click the button and we launch a new piece of UI over the top of everything. You stay in that ‘upper’ UI until you are done and then dismiss this UI to return whence you came down below.

Got that? Great. How would be build that?

Launching something above everything else for some temporary period of time seemed a perfect use case for the dialog element.

OK, my understanding of dialog elements and the top layer at this point…

When you use showModal() the dialog in question is promoted to the ‘top layer’. This lives beyond the normal document confines, allowing the contents of the dialog to live above the DOM. The resultant dialog, when using showModal() is positioned with fixed layout by default and a bunch of user styles. Crucially it also comes with a ::backdrop pseudo element, which, although you can use inset: unset; to allow you to move it around, and even though you might stick display: none on that backdrop pseudo element, the DOM below remains inert as if the backdrop were there anyway.

So, for our ‘upper’ UI, dialog seems a good fit.

But then what when you need to position something on top of that modal dialog?

Crucially, this extra item isn’t full screen, so doesn’t warrant showModal() itself. Well, you might think you could use show() on another sibling dialog instead?

You cannot.

Well, you can, but using show() does not promote this new ‘top’ dialog to the ~Holy Land~ top layer. And as z-index has no powers in or over the top layer, using z-index is a dead-end, it won’t work, it is futile, seriously, it doesn’t work, OK? With show() your dialog is shown, but below the lofty heights of the top layer.

‘Screw this’ you think (I sure did), let’s just make this second upper dialog use showModal() too. That way, if I put it after the first dialog in the DOM, it will surely appear on top?

Yes, but… no.

It appears on top, but have you not been paying attention? Because it is in modal mode, it has a backdrop that even when you kill it off with display: none;, is un-killable like some Freddie Kruger style nightmare pseudo element. Somehow, the contents below this upper dialog remains dead and inert to you.

You can look at this approach here.

So, is that it? Defeat? Are those dev rels touting this months ‘hot new shizzle’ just full of baloney? Is it back to standard elements and good old z-index: 1000?

Not on your nelly pal, we got one last thing to try: popovers.

Even newer than the newish dialog element is the popover API, which at first glance looks like it might be just the ticket.

The Popover API provides developers with a standard, consistent, flexible mechanism for displaying popover content on top of other page content.

Popover API to the rescue?

So, I refactored things a little, changed the second dialog element to a div with the popover attribute. And then rewired the JS to show and hide the new fangled popover instead:

launchTop.addEventListener("click", () => {
  if (isTopShowing) {
    isTopShowing = false;
  } else {
    isTopShowing = true;

You can look at his one here.

At first I was elated. I launched the first dialog in modal mode, and I then clicked the button to launch the popover from the modal and there it was, the popover. I clicked the button on the original modal again and it disappeared. Wow, fantastic, love these new APIs (narrator: “little did he know, he was soon to be swearing at these new APIs”).

That it? Kiss the dame and roll credits? Sadly, this story doesn’t have a happy ending (yet?).

Here is the kicker. You can’t do anything with the contents of this popover when it is sat on top of a modal dialog. Even though you can see the popup, you cannot interact with it. Try clicking the ‘Close Me’ in that example.

However, as soon as you close that dialog, so that you are left with the bottom UI and the popover, you can now interact with the popover as you might expect.

The end

And so here I end this tale of woe, hoping the entirely probable likelihood exists, that I am merely “doing it wrong”. Please, someone, enlighten me.

On the face of it, and admittedly coming at this from a position of rushed naivety, this seems ‘broken’. All this ‘top layer’ stuff is all well and good, but can someone explain, how one has something in a top layer, and then another item above that, that can actually be interacted with?

As ever I’m expected to be schooled on the right way to do this. For now I opened a bug report for Chromium

If it can’t, then there are going to be an awful lot more devs that will continue opting for good ol’ divs and z-index: 1000.