Harald
Harald

Reputation: 5093

How can the HTML <dialog> element be positioned according to normal flow when opened with showModal?

When using a <dialog> element with .show() it is positioned according to normal position etc. CSS properties.

Is it possible to have that same positioning with .showModal()?

Even when using

dialog:modal {
  margin: 0;
  position: relative;
}

to override the browsers position: fixed the dialog ends up in the top left corner (checked with chromium and firefox).

EDIT: copying my comment here for better visibility and avoid more answers about CSS tweaking:

I know how to do computations and move the thing around with top and left. But this is what I would like to avoid.

Meaning I would like to just rip it out of the hands which hold it back as if position:fixed.

const button = document.getElementById('button');
const b2 = document.getElementById('b2');
const dialog = document.getElementById('dialog');
button.addEventListener('click', () => {dialog.showModal();});
b2.addEventListener('click', () => {dialog.show();});
dialog.addEventListener('click', () => {dialog.close();});
#dialog:modal, #dialog {
  margin: 0;
  position: relative;
}
#wrapper {
  background: #fafafa;
  position: relative;
}
<button id="button">open modal</button>
<button id="b2">just show</button>
<div id="wrapper">
  <div>Some context below which the dialog should appear.</div>
  <dialog id="dialog">click to close</dialog>
</div>

Upvotes: 12

Views: 18975

Answers (3)

Nico Ismaili
Nico Ismaili

Reputation: 227

edited 04.03.24; thanks to JGC

Answer

Since the <dialog> element is in it's own layer (see this answer for more information) in relation to the rest of the DOM, it isn't possible to set it as inline, which I understood to be the question.

Positioning <dialog> in general

Also leaving this here for anyone searching for how to position dialogs: SebastianZ mentions in this comment, that the dialog is centered using margin: auto by default. Deactivating margins therefore allows positioning the dialog using absolute coordinates i. e. with top and left.

Example of a centered top dialog:

dialog {
 margin: 0; /* `margin: auto;` is the default. */
 transform: translateX(-50%);
 left: 50%;
}
<dialog open>
Foo
</dialog>

or, if you don't need full control and just want to center the modal at the top of the page:

dialog {
 margin-top: 0;
}
<dialog open>
Foo
</dialog>

Upvotes: 10

kelumden
kelumden

Reputation: 41

Try using margin-right: 0;, and set width and height as needed. It worked for me ! No need for position: it is set to fixed. The dialog is then anchored to the right of the window.

Upvotes: 4

T.J. Crowder
T.J. Crowder

Reputation: 1074148

I hope you find a CSS-only solution, but if you put the dialog in a wrapper div, you can use that div's position to absolutely position the dialog when you show it:

#dialog {
    margin: 0;
    position: absolute;
}
<div id="dialog-wrapper">
    <dialog id="dialog">click to close</dialog>
</div>
button.addEventListener("click", () => {
    const wrapper = document.getElementById("dialog-wrapper");
    dialog.style.left = wrapper.offsetLeft + "px";
    dialog.style.top = wrapper.offsetTop + "px";
    dialog.showModal();
});

Live Example:

const button = document.getElementById("button");
const b2 = document.getElementById("b2");
const dialog = document.getElementById("dialog");
button.addEventListener("click", () => {
    const wrapper = document.getElementById("dialog-wrapper");
    dialog.style.left = wrapper.offsetLeft + "px";
    dialog.style.top = wrapper.offsetTop + "px";
    dialog.showModal();
});
b2.addEventListener("click", () => {
    dialog.show();
});
dialog.addEventListener("click", () => {
    dialog.close();
});
#dialog {
    margin: 0;
    position: absolute;
}
<button id="button">open modal</button>
<button id="b2">just show</button>
<div>
    <div>Some context below which the dialog should appear.</div>
    <div id="dialog-wrapper">
        <dialog id="dialog">click to close</dialog>
    </div>
</div>

Upvotes: 7

Related Questions