Modal

모달

A dialog that dims the whole screen and blocks interaction with the page behind it until it is resolved.

Also known as: DialogModal dialogPopup dialog
···
html
<div class="app-bg"><div class="bar" style="width:60%"></div><div class="bar" style="width:88%"></div><div class="bar" style="width:40%"></div></div>
<div class="overlay" id="ov">
  <div class="modal" role="dialog" aria-modal="true" aria-labelledby="mt">
    <h2 id="mt">항목을 삭제할까요?</h2>
    <p>삭제하면 되돌릴 수 없어요.</p>
    <div class="row"><button class="ghost">취소</button><button class="danger">삭제</button></div>
  </div>
</div>
css
.app-bg{position:absolute;inset:0;padding:18px;display:grid;gap:10px;align-content:start}
.bar{height:10px;border-radius:5px;background:var(--line)}
.overlay{position:absolute;inset:0;background:rgba(10,10,16,.5);display:grid;place-items:center;opacity:0;pointer-events:none;transition:opacity .22s}
.overlay[data-open]{opacity:1;pointer-events:auto}
.modal{width:min(260px,88%);background:var(--surface);border-radius:14px;padding:18px;box-shadow:0 20px 50px rgba(0,0,0,.35);transform:scale(.92) translateY(8px);transition:transform .22s}
.overlay[data-open] .modal{transform:scale(1) translateY(0)}
.modal h2{margin:0 0 6px;font-size:15px}
.modal p{margin:0 0 14px;color:var(--muted);font-size:12px}
.row{display:flex;gap:8px;justify-content:flex-end}
.row button{border:0;border-radius:8px;padding:7px 14px;font-size:12px;font-weight:600;cursor:pointer}
.ghost{background:var(--bg);color:var(--fg);border:1px solid var(--line) !important}
.danger{background:#e5484d;color:#fff}
js
const ov = document.getElementById('ov');
let auto = true;
ov.querySelectorAll('button').forEach((b) => b.addEventListener('click', () => { auto = false; ov.removeAttribute('data-open'); }));
ov.addEventListener('click', (e) => { if (e.target === ov) { auto = false; ov.removeAttribute('data-open'); } });
function loop() { if (!auto) return; ov.setAttribute('data-open', ''); setTimeout(() => { if (auto) { ov.removeAttribute('data-open'); setTimeout(loop, 1200); } }, 2200); }
ov.setAttribute('data-open', '');
setTimeout(loop, 2200);

The native <dialog showModal()> gives you focus trapping and top-layer stacking for free. If you build one by hand, set role="dialog" aria-modal="true", move focus inside on open (usually the title or first field), trap Tab so it can't escape the dialog, and return focus to the trigger button on close.

It's often compared with a drawer. A modal centers on screen and reads as "deal with this now," while a drawer slides in from an edge and is used for lighter supporting tasks — filters, settings — sometimes built as non-modal so the page behind stays usable.

Esc and backdrop-click closing are conventional, but a form that could lose data should ask for confirmation before closing that way.

When to use

Reserve it for moments that truly block progress until the user decides — delete confirmations. For informational messages, a toast is less disruptive.