I have a dropdown control which is implemented a dialog (seems a div would behave the same), any way to place it over a modal dialog so it would behave as a dropdown and be independent of the modal? Tried several things with z-index
, no luck:
modal.showModal();
.dialog,
.popup {
z-index: 100000;
position: absolute;
}
#modal {
z-index: 1000;
top: 90px;
}
.popup {
top: 70px;
background: #faa;
border: 1px solid gray;
}
dialog,
.popup {
width: 400px;
height: 300px;
}
<dialog open class="dialog">Dialog</dialog>
<div class="popup">Popup</div>
<dialog id="modal">Modal
<dialog open class="dialog">Dialog</dialog>
<div class="popup">Popup</div>
</dialog>
1
There’s two ways to open a <dialog>
:
-
With the
.showModal()
method the<dialog>
behaves as a modal. A modal will block the rest of the page from user interaction so a dropdown would definitely be inaccessible while a modal is open. -
Or with the
.show()
method which makes it behave as a dialog. A dialog does not interfere with user interaction with the page so a dropdown is definitely accessible while a dialog is open.
If you want the <dialog>
to be open when the page loads, use the methods instead of the [open]
attribute because you’ll have more control and more options. In the example below, there two <button>
s that open a <dialog>
both ways. There’s also a dropdown to test both modes with. Details are commented in the example.
// Reference <dialog>
const popup = document.getElementById("popup");
// Reference the first <form>
const bg = document.forms.btnGrp;
// Reference all <button>s in first <form>
const io = bg.elements;
// Reference the second <form>
const df = document.forms.dmForm;
// Reference all <button>s, <fieldset>s, and <output> in second <form>
const oi = df.elements;
// Reference <output>
const msg = oi.message;
// Bind first <form> to the "submit" event in order to prevent redirect
bg.onsubmit = e => e.preventDefault();
/**
* Bind #modBtn to the "click" event. When event is triggered:
* - the .showModal() method open #popup as a modal
* - #message will display blue text
* - #modBtn and #dlgBtn will be disabled
*/
io.modBtn.onclick = e => {
popup.showModal();
msg.value = `This is a modal not a dialog.`;
io.dlgBtn.toggleAttribute("disabled");
e.target.toggleAttribute("disabled");
}
/**
* Bind #dlgBtn to the "click" event. When event is triggered:
* - the .show() method open #popup as a dialog
* - #message will display blue text
* - #modBtn and #dlgBtn will be disabled
*/
io.dlgBtn.onclick = e => {
popup.show();
msg.value = `This is a dialog not a modal.`;
io.modBtn.toggleAttribute("disabled");
e.target.toggleAttribute("disabled");
}
/**
* Bind #popup to the "close" event. When #popup closes #dlgBtn and #modBtn
* will be re-enabled
*/
popup.onclose = e => {
io.modBtn.toggleAttribute("disabled");
io.dlgBtn.toggleAttribute("disabled");
}
:root {
font: 4vmin/1.1 "Segoe UI"
}
body {
background: #bbb;
}
main {
position: relative;
}
header {
display: flex;
justify-content: space-between;
align-items: center;
height: 1.5rem;
padding: 0.5rem 1rem 0.25rem;
border-bottom: 3px outset grey;
}
#dropdown {
position: absolute;
z-index: 100;
top: -0.25rem;
left: 0;
width: 50%;
background: #ddd;
}
summary {
padding: 0.25rem 0.75rem;
cursor: pointer
}
.navLnx {
list-style: none;
padding: 0
}
li {
margin-bottom: 0.25rem
}
a {
display: block;
width: 100%;
}
#btnGrp {
position: absolute;
top: -0.2rem;
right: 0;
height: fit-content;
padding: 0;
}
#dmForm {
display: flex;
justify-content: center;
}
button {
font: inherit;
cursor: pointer
}
#popup {
max-width: 70vw;
border: 0;
background: transparent;
}
#popup::backdrop {
background: rgba(0 0 0 / 50%);
}
fieldset {
padding-bottom: 0.75rem;
border: 0;
border-radius: 8px;
background: #fff;
}
legend {
margin-bottom: 0.5rem;
padding: 0.25rem 0;
border: 0;
font-size: 1.1rem;
transform: translateY(1.25rem);
}
#message {
font: inherit;
font-weight: 500;
color: blue;
}
#popup ul {
margin-right: 1rem;
}
<main>
<header>
<details id="dropdown">
<summary>Dropdown</summary>
<nav>
<menu class="navLnx">
<li><a href="/">0</a></li>
<li><a href="/">1</a></li>
<li><a href="/">2</a></li>
<li><a href="/">3</a></li>
<li><a href="/">4</a></li>
<li><a href="/">5</a></li>
<li><a href="/">6</a></li>
<li><a href="/">7</a></li>
<li><a href="/">8</a></li>
<li><a href="/">9</a></li>
<li><a href="/">A</a></li>
<li><a href="/">B</a></li>
<li><a href="/">C</a></li>
<li><a href="/">D</a></li>
<li><a href="/">E</a></li>
<li><a href="/">F</a></li>
</menu>
</nav>
</details>
<form id="btnGrp">
<button id="modBtn">Modal</button>
<button id="dlgBtn">Dialog</button>
</form>
</header>
<dialog id="popup">
<fieldset>
<legend>Modal or Dialog?</legend>
<p>
<output id="message" form="dmForm"></output>
</p>
<ul>
<li>A modal takes priority and focus from everything else on the page. Normal interaction is blocked with the exception being the modal of course.</li>
<li>A dialog doesn't monopolize the user's attention and interaction with the page is possible whilst the dialog is open.</li>
</ul>
<p>The OP probably wants the latter.</p>
<form id="dmForm" method="dialog">
<button>OK</button>
</form>
</fieldset>
</dialog>
</main>
0
There is no problem about open a modal hover an open one…
modal1.showModal();
modal2.showModal();
#modal1 {
width: 400px;
height: 300px;
}
#modal1::backdrop {
background: rgba(255,0,0,.4);
}
#modal2 {
width: 200px;
height: 100px;
}
#modal2::backdrop {
background: rgba(0,0,255,.4);
}
<dialog id="modal1">modal 1 use escape</dialog>
<dialog id="modal2">modal 2 use escape</dialog>
Thanks for the answers, I’ve just decided to open the modal full page size and use it as a top layer window where I show the actual dialog like container and every other dropdowns added to it (not to the body) will behave as i need