[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"verticals":3,"article-dialog-element-native-modal":32,"code:html:true:wq47fe":256,"code:js:true:1eiyx74":257,"code:js:true:1qc3e5v":258,"code:css:true:1s7n687":259,"code:css:true:yxwz0r":260,"code:js:true:5ev235":261,"code:js:true:1e0b9ol":262,"code:html:true:6lu25e":263,"code:js:true:8a5z67":264},[4,20],{"id":5,"slug":6,"name":7,"tagline":8,"description":9,"accentFrom":10,"accentTo":11,"icon":12,"defaultLocale":13,"locales":14,"features":16,"position":19},"019fe637-3d33-714b-b57f-23e163ffca0c","dev","Web Development","Build. Learn. Ship.","Practical courses, engineering-grade articles and open-source tools for people who ship.","violet-500","cyan-400","◇","en",[13,15],"fa",{"courses":17,"paths":17,"articles":17,"exams":18,"flashcards":18,"packages":17,"community":17,"certificates":17,"teams":17,"commerce":17},true,false,0,{"id":21,"slug":22,"name":23,"tagline":24,"description":25,"accentFrom":26,"accentTo":10,"icon":27,"defaultLocale":13,"locales":28,"features":30,"position":31},"019fe637-3dc2-754c-8657-0f175bfee7c6","lang","Languages","Learn a language the way you learn a codebase.","Structured paths, listening drills and spaced repetition that actually sticks.","amber-400","⌘",[13,15,29],"es",{"courses":17,"paths":17,"articles":18,"exams":18,"flashcards":18,"packages":18,"community":17,"certificates":18,"teams":18,"commerce":17},2,{"id":33,"slug":34,"title":35,"subtitle":36,"excerpt":37,"coverUrl":38,"locale":13,"readingMinutes":39,"publishedAt":40,"viewCount":41,"likeCount":19,"commentCount":19,"author":42,"vertical":47,"topic":48,"tags":51,"_count":63,"playground":65,"body":67,"bodyMd":239,"seo":240,"translationGroupId":243,"thread":244,"assessments":246,"translations":252,"quiz":254},"019ff19b-f388-73f8-aa5b-93d73337d6fd","dialog-element-native-modal","You built your modal with a `\u003Cdiv>` and a focus trap library. The native `\u003Cdialog>` does all of that.",null,"The `\u003Cdialog>` element ships with focus trapping, Escape-to-close, backdrop rendering, and correct ARIA semantics — no library, no boilerplate. It's been Baseline since 2022.","\u002Fmedia\u002Fcovers\u002Fdialog-element-native-modal.png",5,"2026-08-08T07:00:10.810Z",51,{"id":43,"name":44,"username":45,"avatarUrl":36,"headline":46},"019fe637-3c25-7088-9034-39c9f15dc3c8","Parsa Jiravand","parsa","Frontend engineer · building bestpractic",{"slug":6,"name":7,"accentFrom":10,"accentTo":11},{"slug":49,"name":50},"html","HTML",[52,54,57,60],{"slug":49,"name":53,"color":36},"Html",{"slug":55,"name":56,"color":36},"webdev","Webdev",{"slug":58,"name":59,"color":36},"frontend","Frontend",{"slug":61,"name":62,"color":36},"javascript","Javascript",{"assessments":64},1,{"slug":34,"title":66},"&lt;dialog&gt; — interactive playground",{"blocks":68,"version":64},[69,73,76,80,85,90,93,97,100,103,106,110,113,116,121,124,127,130,134,137,140,143,147,150,154,157,161,164,168,171,175,179,182,185,188,191,194,197,200,203,206,209,212,215,218,221,224,227,230],{"id":70,"html":71,"type":72},"b1","\u003Cp>Building a modal from scratch means writing the same boilerplate every time: a \u003Ccode>&lt;div&gt;\u003C\u002Fcode> with \u003Ccode>role=&quot;dialog&quot;\u003C\u002Fcode>, an \u003Ccode>aria-modal\u003C\u002Fcode> attribute, a \u003Ccode>tabindex=&quot;-1&quot;\u003C\u002Fcode> to steal focus, a \u003Ccode>keydown\u003C\u002Fcode> listener to catch Escape, a focus-trap library to keep Tab cycling inside the dialog, and a \u003Ccode>click\u003C\u002Fcode> listener on the backdrop overlay you rendered yourself. It works, but you&#39;re doing the browser&#39;s job.\u003C\u002Fp>","paragraph",{"id":74,"html":75,"type":72},"b2","\u003Cp>The \u003Ccode>&lt;dialog&gt;\u003C\u002Fcode> element exists to take that job back.\u003C\u002Fp>",{"id":77,"html":78,"text":78,"type":79,"level":31},"b3","The baseline API","heading",{"id":81,"code":82,"type":83,"language":49,"highlight":84},"b4","\u003Cdialog id=\"confirm-dialog\">\n  \u003Ch2>Delete item?\u003C\u002Fh2>\n  \u003Cp>This cannot be undone.\u003C\u002Fp>\n  \u003Cbutton id=\"cancel-btn\">Cancel\u003C\u002Fbutton>\n  \u003Cbutton id=\"confirm-btn\">Confirm\u003C\u002Fbutton>\n\u003C\u002Fdialog>\n\n\u003Cbutton id=\"open-btn\">Delete\u003C\u002Fbutton>","code",[],{"id":86,"code":87,"type":83,"language":88,"highlight":89},"b5","const dialog = document.getElementById('confirm-dialog');\nconst openBtn = document.getElementById('open-btn');\nconst cancelBtn = document.getElementById('cancel-btn');\nconst confirmBtn = document.getElementById('confirm-btn');\n\nopenBtn.addEventListener('click', () => dialog.showModal());\ncancelBtn.addEventListener('click', () => dialog.close());\nconfirmBtn.addEventListener('click', () => {\n  deleteItem();\n  dialog.close();\n});","js",[],{"id":91,"html":92,"type":72},"b6","\u003Cp>That&#39;s it. The browser handles focus trapping (Tab stays inside), Escape-to-close, and ARIA role. No library. No \u003Ccode>keydown\u003C\u002Fcode> listener. No backdrop div.\u003C\u002Fp>",{"id":94,"html":95,"text":96,"type":79,"level":31},"b7","\u003Ccode>showModal()\u003C\u002Fcode> vs \u003Ccode>show()\u003C\u002Fcode>","showModal() vs show()",{"id":98,"html":99,"type":72},"b8","\u003Cp>The element has two open methods and they are meaningfully different.\u003C\u002Fp>",{"id":101,"html":102,"type":72},"b9","\u003Cp>\u003Ccode>dialog.show()\u003C\u002Fcode> opens the dialog as a \u003Cstrong>non-modal\u003C\u002Fstrong>: it&#39;s visible, but the rest of the page is still interactive. Useful for inline panels, drawers, or toasts — not for blocking confirmation flows.\u003C\u002Fp>",{"id":104,"html":105,"type":72},"b10","\u003Cp>\u003Ccode>dialog.showModal()\u003C\u002Fcode> opens it as a \u003Cstrong>modal\u003C\u002Fstrong>: the browser places the dialog in the \u003Ca href=\"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FGlossary\u002FTop_layer\">top layer\u003C\u002Fa> — above all other content, including elements with high \u003Ccode>z-index\u003C\u002Fcode> — and blocks interaction with everything beneath. Focus is trapped inside. Escape closes it. This is what you actually want for a modal dialog.\u003C\u002Fp>",{"id":107,"code":108,"type":83,"language":88,"highlight":109},"b11","dialog.show();      \u002F\u002F non-modal — rest of page still interactive\ndialog.showModal(); \u002F\u002F modal — top layer, focus trapped, Escape works",[],{"id":111,"html":112,"text":112,"type":79,"level":31},"b12","Styling the backdrop",{"id":114,"html":115,"type":72},"b13","\u003Cp>When opened with \u003Ccode>showModal()\u003C\u002Fcode>, the browser renders a backdrop behind the dialog and above the rest of the page. You style it with the \u003Ccode>::backdrop\u003C\u002Fcode> pseudo-element:\u003C\u002Fp>",{"id":117,"code":118,"type":83,"language":119,"highlight":120},"b14","dialog::backdrop {\n  background: rgb(0 0 0 \u002F 50%);\n  backdrop-filter: blur(4px);\n}","css",[],{"id":122,"html":123,"type":72},"b15","\u003Cp>No more \u003Ccode>position: fixed; inset: 0; background: rgba(0,0,0,0.5)\u003C\u002Fcode> divs. The browser-rendered backdrop is always in the right place, covers the right things, and is animated by the dialog&#39;s own open\u002Fclose transitions.\u003C\u002Fp>",{"id":125,"html":126,"text":126,"type":79,"level":31},"b16","Animating open and close",{"id":128,"html":129,"type":72},"b17","\u003Cp>The \u003Ccode>&lt;dialog&gt;\u003C\u002Fcode> element pairs naturally with \u003Ccode>@starting-style\u003C\u002Fcode> for entry animations. For the exit, you need a small JS helper because the dialog&#39;s \u003Ccode>close()\u003C\u002Fcode> method removes the \u003Ccode>open\u003C\u002Fcode> attribute before a CSS exit transition can play:\u003C\u002Fp>",{"id":131,"code":132,"type":83,"language":119,"highlight":133},"b18","dialog {\n  opacity: 0;\n  transform: scale(0.95);\n  transition: opacity 200ms, transform 200ms, display 200ms allow-discrete;\n}\n\ndialog[open] {\n  opacity: 1;\n  transform: scale(1);\n}\n\n@starting-style {\n  dialog[open] {\n    opacity: 0;\n    transform: scale(0.95);\n  }\n}",[],{"id":135,"html":136,"type":72},"b19","\u003Cp>With \u003Ccode>allow-discrete\u003C\u002Fcode> on the \u003Ccode>display\u003C\u002Fcode> transition (Chrome 117+), the browser holds the dialog in the layout for the duration of the exit transition before hiding it. For older targets, a small \u003Ccode>setTimeout\u003C\u002Fcode> before \u003Ccode>dialog.close()\u003C\u002Fcode> is the reliable fallback.\u003C\u002Fp>",{"id":138,"html":139,"text":139,"type":79,"level":31},"b20","Handling backdrop clicks to close",{"id":141,"html":142,"type":72},"b21","\u003Cp>The backdrop is not a separate element you can listen to directly. The reliable pattern uses the dialog&#39;s own \u003Ccode>click\u003C\u002Fcode> event and checks whether the click landed inside the dialog&#39;s bounding box:\u003C\u002Fp>",{"id":144,"code":145,"type":83,"language":88,"highlight":146},"b22","dialog.addEventListener('click', (event) => {\n  const rect = dialog.getBoundingClientRect();\n  const clickedOutside =\n    event.clientX \u003C rect.left ||\n    event.clientX > rect.right ||\n    event.clientY \u003C rect.top ||\n    event.clientY > rect.bottom;\n\n  if (clickedOutside) dialog.close();\n});",[],{"id":148,"html":149,"type":72},"b23","\u003Cp>The reason this works: when you click the backdrop, the \u003Ccode>&lt;dialog&gt;\u003C\u002Fcode> element itself receives the event — the click target is the dialog, not an element inside it. The bounding box check distinguishes backdrop clicks from content clicks cleanly.\u003C\u002Fp>",{"id":151,"html":152,"text":153,"type":79,"level":31},"b24","Return value from \u003Ccode>close()\u003C\u002Fcode>","Return value from close()",{"id":155,"html":156,"type":72},"b25","\u003Cp>\u003Ccode>dialog.close()\u003C\u002Fcode> accepts an optional string argument that becomes the dialog&#39;s \u003Ccode>returnValue\u003C\u002Fcode>. This lets you communicate \u003Cem>why\u003C\u002Fem> the dialog closed without external state:\u003C\u002Fp>",{"id":158,"code":159,"type":83,"language":88,"highlight":160},"b26","confirmBtn.addEventListener('click', () => dialog.close('confirmed'));\ncancelBtn.addEventListener('click', () => dialog.close('cancelled'));\n\ndialog.addEventListener('close', () => {\n  if (dialog.returnValue === 'confirmed') deleteItem();\n});",[],{"id":162,"html":163,"type":72},"b27","\u003Cp>The \u003Ccode>close\u003C\u002Fcode> event fires whenever the dialog closes — via \u003Ccode>close()\u003C\u002Fcode>, Escape, or a \u003Ccode>&lt;form method=&quot;dialog&quot;&gt;\u003C\u002Fcode> submission. Combined with \u003Ccode>returnValue\u003C\u002Fcode>, it gives you a clean interface for confirmation flows without threading state through callbacks.\u003C\u002Fp>",{"id":165,"html":166,"text":167,"type":79,"level":31},"b28","The \u003Ccode>&lt;form method=&quot;dialog&quot;&gt;\u003C\u002Fcode> shortcut","The \u003Cform method=\"dialog\"> shortcut",{"id":169,"html":170,"type":72},"b29","\u003Cp>If you put a \u003Ccode>&lt;form method=&quot;dialog&quot;&gt;\u003C\u002Fcode> inside a \u003Ccode>&lt;dialog&gt;\u003C\u002Fcode>, any submit button closes the dialog automatically and sets \u003Ccode>returnValue\u003C\u002Fcode> to the button&#39;s \u003Ccode>value\u003C\u002Fcode> attribute — no JavaScript needed for the close logic:\u003C\u002Fp>",{"id":172,"code":173,"type":83,"language":49,"highlight":174},"b30","\u003Cdialog id=\"confirm-dialog\">\n  \u003Cform method=\"dialog\">\n    \u003Ch2>Delete item?\u003C\u002Fh2>\n    \u003Cbutton value=\"cancelled\">Cancel\u003C\u002Fbutton>\n    \u003Cbutton value=\"confirmed\">Confirm\u003C\u002Fbutton>\n  \u003C\u002Fform>\n\u003C\u002Fdialog>",[],{"id":176,"code":177,"type":83,"language":88,"highlight":178},"b31","dialog.addEventListener('close', () => {\n  if (dialog.returnValue === 'confirmed') deleteItem();\n});",[],{"id":180,"html":181,"type":72},"b32","\u003Cp>The form doesn&#39;t submit to a server — \u003Ccode>method=&quot;dialog&quot;\u003C\u002Fcode> is a special value that routes the submission back to the dialog element itself. Useful for simple flows; for complex forms with validation, you&#39;ll still handle submission explicitly.\u003C\u002Fp>",{"id":183,"html":184,"text":184,"type":79,"level":31},"b33","Browser support",{"id":186,"html":187,"type":72},"b34","\u003Cp>\u003Ccode>&lt;dialog&gt;\u003C\u002Fcode> is \u003Cstrong>Baseline 2022\u003C\u002Fstrong>: Chrome 98, Firefox 98, Safari 15.4. Global support is above 95%. You do not need a polyfill for production today. The only missing piece in some older browsers is \u003Ccode>::backdrop\u003C\u002Fcode> styling — the functional modal behavior (focus trap, Escape, top layer) is universally supported.\u003C\u002Fp>",{"id":189,"html":190,"type":72},"b35","\u003C!-- playground:start -->",{"id":192,"html":193,"text":193,"type":79,"level":31},"b36","🎮 Try it yourself",{"id":195,"html":196,"type":72},"b37","\u003Cp>\u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-08-08-dialog-element-native-modal\u002Fplayground\u002F\">▶️ Open the interactive playground →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":198,"html":199,"type":72},"b38","\u003Cp>\u003Cem>Runs right in your browser — poke at it and watch the concept react live.\u003C\u002Fem>\u003C\u002Fp>",{"id":201,"html":202,"type":72},"b39","\u003C!-- playground:end -->",{"id":204,"html":205,"type":72},"b40","\u003C!-- quiz:start -->",{"id":207,"html":208,"text":208,"type":79,"level":31},"b41","🧠 Test yourself",{"id":210,"html":211,"type":72},"b42","\u003Cp>Think it clicked? \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-08-08-dialog-element-native-modal\">Take the 8-question quiz →\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>",{"id":213,"html":214,"type":72},"b43","\u003Cp>\u003Cem>Instant feedback, a hint on every question, and an explanation for each answer — right or wrong.\u003C\u002Fem>\u003C\u002Fp>",{"id":216,"html":217,"type":72},"b44","\u003C!-- quiz:end -->",{"id":219,"html":220,"text":220,"type":79,"level":31},"b45","The takeaway",{"id":222,"html":223,"type":72},"b46","\u003Cp>Search your codebase for \u003Ccode>role=&quot;dialog&quot;\u003C\u002Fcode> and the focus-trap imports that live near it. Each one is a candidate for replacement: \u003Ccode>&lt;dialog&gt;\u003C\u002Fcode> with \u003Ccode>showModal()\u003C\u002Fcode> handles focus trapping, Escape, backdrop, and ARIA semantics — a library bought you those because the platform didn&#39;t provide them. It does now. Start with the simplest confirmation dialog in your UI, replace it with \u003Ccode>&lt;dialog&gt;\u003C\u002Fcode> and \u003Ccode>showModal()\u003C\u002Fcode>, and you&#39;ll notice what disappears: the \u003Ccode>keydown\u003C\u002Fcode> listener, the backdrop div, the z-index war, and the focus-management ceremony. What remains is the logic that was actually yours to write.\u003C\u002Fp>",{"id":225,"type":226},"b47","divider",{"id":228,"html":229,"type":72},"b48","\u003Cp>\u003Cem>Thanks for reading! Let&#39;s stay connected:\u003C\u002Fem>\u003C\u002Fp>",{"id":231,"type":232,"items":233,"ordered":18},"b49","list",[234,235,236,237,238],"⭐ \u003Cstrong>GitHub\u003C\u002Fstrong> — follow me and star the projects: \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fparsajiravand\">github.com\u002Fparsajiravand\u003C\u002Fa>","💬 \u003Cstrong>Discord\u003C\u002Fstrong> — join the frontend best-practices community: \u003Ca href=\"https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ\">discord.gg\u002Fd9KRhuAwQ\u003C\u002Fa>","📸 \u003Cstrong>Instagram\u003C\u002Fstrong> — frontend best practices, daily: \u003Ca href=\"https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F\">@bestpractice___\u003C\u002Fa>","💼 \u003Cstrong>LinkedIn\u003C\u002Fstrong> — \u003Ca href=\"https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F\">linkedin.com\u002Fin\u002Fparsa-jiravand\u003C\u002Fa>","✉️ \u003Cstrong>Email\u003C\u002Fstrong> (work &amp; contract inquiries): \u003Ca href=\"mailto:bestpractice2026@gmail.com\">bestpractice2026@gmail.com\u003C\u002Fa>","Building a modal from scratch means writing the same boilerplate every time: a `\u003Cdiv>` with `role=\"dialog\"`, an `aria-modal` attribute, a `tabindex=\"-1\"` to steal focus, a `keydown` listener to catch Escape, a focus-trap library to keep Tab cycling inside the dialog, and a `click` listener on the backdrop overlay you rendered yourself. It works, but you're doing the browser's job.\n\nThe `\u003Cdialog>` element exists to take that job back.\n\n## The baseline API\n\n```html\n\u003Cdialog id=\"confirm-dialog\">\n  \u003Ch2>Delete item?\u003C\u002Fh2>\n  \u003Cp>This cannot be undone.\u003C\u002Fp>\n  \u003Cbutton id=\"cancel-btn\">Cancel\u003C\u002Fbutton>\n  \u003Cbutton id=\"confirm-btn\">Confirm\u003C\u002Fbutton>\n\u003C\u002Fdialog>\n\n\u003Cbutton id=\"open-btn\">Delete\u003C\u002Fbutton>\n```\n\n```js\nconst dialog = document.getElementById('confirm-dialog');\nconst openBtn = document.getElementById('open-btn');\nconst cancelBtn = document.getElementById('cancel-btn');\nconst confirmBtn = document.getElementById('confirm-btn');\n\nopenBtn.addEventListener('click', () => dialog.showModal());\ncancelBtn.addEventListener('click', () => dialog.close());\nconfirmBtn.addEventListener('click', () => {\n  deleteItem();\n  dialog.close();\n});\n```\n\nThat's it. The browser handles focus trapping (Tab stays inside), Escape-to-close, and ARIA role. No library. No `keydown` listener. No backdrop div.\n\n## `showModal()` vs `show()`\n\nThe element has two open methods and they are meaningfully different.\n\n`dialog.show()` opens the dialog as a **non-modal**: it's visible, but the rest of the page is still interactive. Useful for inline panels, drawers, or toasts — not for blocking confirmation flows.\n\n`dialog.showModal()` opens it as a **modal**: the browser places the dialog in the [top layer](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FGlossary\u002FTop_layer) — above all other content, including elements with high `z-index` — and blocks interaction with everything beneath. Focus is trapped inside. Escape closes it. This is what you actually want for a modal dialog.\n\n```js\ndialog.show();      \u002F\u002F non-modal — rest of page still interactive\ndialog.showModal(); \u002F\u002F modal — top layer, focus trapped, Escape works\n```\n\n## Styling the backdrop\n\nWhen opened with `showModal()`, the browser renders a backdrop behind the dialog and above the rest of the page. You style it with the `::backdrop` pseudo-element:\n\n```css\ndialog::backdrop {\n  background: rgb(0 0 0 \u002F 50%);\n  backdrop-filter: blur(4px);\n}\n```\n\nNo more `position: fixed; inset: 0; background: rgba(0,0,0,0.5)` divs. The browser-rendered backdrop is always in the right place, covers the right things, and is animated by the dialog's own open\u002Fclose transitions.\n\n## Animating open and close\n\nThe `\u003Cdialog>` element pairs naturally with `@starting-style` for entry animations. For the exit, you need a small JS helper because the dialog's `close()` method removes the `open` attribute before a CSS exit transition can play:\n\n```css\ndialog {\n  opacity: 0;\n  transform: scale(0.95);\n  transition: opacity 200ms, transform 200ms, display 200ms allow-discrete;\n}\n\ndialog[open] {\n  opacity: 1;\n  transform: scale(1);\n}\n\n@starting-style {\n  dialog[open] {\n    opacity: 0;\n    transform: scale(0.95);\n  }\n}\n```\n\nWith `allow-discrete` on the `display` transition (Chrome 117+), the browser holds the dialog in the layout for the duration of the exit transition before hiding it. For older targets, a small `setTimeout` before `dialog.close()` is the reliable fallback.\n\n## Handling backdrop clicks to close\n\nThe backdrop is not a separate element you can listen to directly. The reliable pattern uses the dialog's own `click` event and checks whether the click landed inside the dialog's bounding box:\n\n```js\ndialog.addEventListener('click', (event) => {\n  const rect = dialog.getBoundingClientRect();\n  const clickedOutside =\n    event.clientX \u003C rect.left ||\n    event.clientX > rect.right ||\n    event.clientY \u003C rect.top ||\n    event.clientY > rect.bottom;\n\n  if (clickedOutside) dialog.close();\n});\n```\n\nThe reason this works: when you click the backdrop, the `\u003Cdialog>` element itself receives the event — the click target is the dialog, not an element inside it. The bounding box check distinguishes backdrop clicks from content clicks cleanly.\n\n## Return value from `close()`\n\n`dialog.close()` accepts an optional string argument that becomes the dialog's `returnValue`. This lets you communicate *why* the dialog closed without external state:\n\n```js\nconfirmBtn.addEventListener('click', () => dialog.close('confirmed'));\ncancelBtn.addEventListener('click', () => dialog.close('cancelled'));\n\ndialog.addEventListener('close', () => {\n  if (dialog.returnValue === 'confirmed') deleteItem();\n});\n```\n\nThe `close` event fires whenever the dialog closes — via `close()`, Escape, or a `\u003Cform method=\"dialog\">` submission. Combined with `returnValue`, it gives you a clean interface for confirmation flows without threading state through callbacks.\n\n## The `\u003Cform method=\"dialog\">` shortcut\n\nIf you put a `\u003Cform method=\"dialog\">` inside a `\u003Cdialog>`, any submit button closes the dialog automatically and sets `returnValue` to the button's `value` attribute — no JavaScript needed for the close logic:\n\n```html\n\u003Cdialog id=\"confirm-dialog\">\n  \u003Cform method=\"dialog\">\n    \u003Ch2>Delete item?\u003C\u002Fh2>\n    \u003Cbutton value=\"cancelled\">Cancel\u003C\u002Fbutton>\n    \u003Cbutton value=\"confirmed\">Confirm\u003C\u002Fbutton>\n  \u003C\u002Fform>\n\u003C\u002Fdialog>\n```\n\n```js\ndialog.addEventListener('close', () => {\n  if (dialog.returnValue === 'confirmed') deleteItem();\n});\n```\n\nThe form doesn't submit to a server — `method=\"dialog\"` is a special value that routes the submission back to the dialog element itself. Useful for simple flows; for complex forms with validation, you'll still handle submission explicitly.\n\n## Browser support\n\n`\u003Cdialog>` is **Baseline 2022**: Chrome 98, Firefox 98, Safari 15.4. Global support is above 95%. You do not need a polyfill for production today. The only missing piece in some older browsers is `::backdrop` styling — the functional modal behavior (focus trap, Escape, top layer) is universally supported.\n\n\n\u003C!-- playground:start -->\n\n## 🎮 Try it yourself\n\n**[▶️ Open the interactive playground →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fposts\u002F2026-08-08-dialog-element-native-modal\u002Fplayground\u002F)**\n\n_Runs right in your browser — poke at it and watch the concept react live._\n\n\u003C!-- playground:end -->\n\n\u003C!-- quiz:start -->\n\n## 🧠 Test yourself\n\nThink it clicked? **[Take the 8-question quiz →](https:\u002F\u002Fdaily-post-dev.netlify.app\u002Fquiz\u002Ftake.html?post=2026-08-08-dialog-element-native-modal)**\n\n_Instant feedback, a hint on every question, and an explanation for each answer — right or wrong._\n\n\u003C!-- quiz:end -->\n## The takeaway\n\nSearch your codebase for `role=\"dialog\"` and the focus-trap imports that live near it. Each one is a candidate for replacement: `\u003Cdialog>` with `showModal()` handles focus trapping, Escape, backdrop, and ARIA semantics — a library bought you those because the platform didn't provide them. It does now. Start with the simplest confirmation dialog in your UI, replace it with `\u003Cdialog>` and `showModal()`, and you'll notice what disappears: the `keydown` listener, the backdrop div, the z-index war, and the focus-management ceremony. What remains is the logic that was actually yours to write.\n\n---\n\n*Thanks for reading! Let's stay connected:*\n\n- ⭐ **GitHub** — follow me and star the projects: [github.com\u002Fparsajiravand](https:\u002F\u002Fgithub.com\u002Fparsajiravand)\n- 💬 **Discord** — join the frontend best-practices community: [discord.gg\u002Fd9KRhuAwQ](https:\u002F\u002Fdiscord.gg\u002Fd9KRhuAwQ)\n- 📸 **Instagram** — frontend best practices, daily: [@bestpractice___](https:\u002F\u002Fwww.instagram.com\u002Fbestpractice___\u002F)\n- 💼 **LinkedIn** — [linkedin.com\u002Fin\u002Fparsa-jiravand](https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fparsa-jiravand\u002F)\n- ✉️ **Email** (work & contract inquiries): [bestpractice2026@gmail.com](mailto:bestpractice2026@gmail.com)",{"title":241,"canonical":242,"description":37},"You built your modal with a `\u003Cdiv>` and a focus trap library. The nati","https:\u002F\u002Fbestpractic.org\u002Fblog\u002Fdialog-element-native-modal","019ff19b-f388-73f8-aa5b-97670f13d581",{"id":245,"locked":18},"019ff19b-f3a1-7259-882a-24fdc8bb3f32",[247],{"id":248,"slug":34,"title":249,"_count":250},"019ff19b-f3ba-73aa-9313-c2d3237b0363","Native \u003Cdialog> element",{"questions":251},8,[253],{"locale":13,"slug":34},{"id":248,"slug":34,"title":249,"_count":255,"questionCount":251},{"questions":251},"\u003Cdiv class=\"shj shj-lang-html shj-multiline\" data-lang=\"html\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">dialog\u003C\u002Fspan> \u003Cspan class=\"shj-class\">id\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"confirm-dialog\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">h2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>Delete item?\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">h2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">p\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>This cannot be undone.\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">p\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">button\u003C\u002Fspan> \u003Cspan class=\"shj-class\">id\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"cancel-btn\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>Cancel\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">button\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">button\u003C\u002Fspan> \u003Cspan class=\"shj-class\">id\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"confirm-btn\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>Confirm\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">button\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">dialog\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n\n\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">button\u003C\u002Fspan> \u003Cspan class=\"shj-class\">id\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"open-btn\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>Delete\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">button\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> dialog \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getElementById\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'confirm-dialog'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> openBtn \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getElementById\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'open-btn'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> cancelBtn \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getElementById\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'cancel-btn'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> confirmBtn \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> document\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getElementById\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'confirm-btn'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\nopenBtn\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'click'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">showModal\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\ncancelBtn\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'click'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">close\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\nconfirmBtn\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'click'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-func\">deleteItem\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">close\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">show\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;      \u003Cspan class=\"shj-cmnt\">\u002F\u002F non-modal — rest of page still interactive\n\u003C\u002Fspan>dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">showModal\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>; \u003Cspan class=\"shj-cmnt\">\u002F\u002F modal — top layer, focus trapped, Escape works\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-css shj-multiline\" data-lang=\"css\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">dialog\u003C\u002Fspan>\u003Cspan class=\"shj-var\">::backdrop\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">background\u003C\u002Fspan>: \u003Cspan class=\"shj-func\">rgb\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">0\u003C\u002Fspan> \u003Cspan class=\"shj-num\">0\u003C\u002Fspan> \u003Cspan class=\"shj-num\">0\u003C\u002Fspan> \u002F \u003Cspan class=\"shj-num\">50\u003C\u002Fspan>\u003Cspan class=\"shj-var\">%\u003C\u002Fspan>\u003Cspan class=\"shj-num\">\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-var\">backdrop-filter\u003C\u002Fspan>: \u003Cspan class=\"shj-func\">blur\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">4\u003C\u002Fspan>\u003Cspan class=\"shj-var\">px\u003C\u002Fspan>\u003Cspan class=\"shj-num\">\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-css shj-multiline\" data-lang=\"css\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003Cdiv>11\u003C\u002Fdiv>\u003Cdiv>12\u003C\u002Fdiv>\u003Cdiv>13\u003C\u002Fdiv>\u003Cdiv>14\u003C\u002Fdiv>\u003Cdiv>15\u003C\u002Fdiv>\u003Cdiv>16\u003C\u002Fdiv>\u003Cdiv>17\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-kwd\">dialog\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">opacity\u003C\u002Fspan>: \u003Cspan class=\"shj-num\">0\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-var\">transform\u003C\u002Fspan>: \u003Cspan class=\"shj-func\">scale\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">0.95\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-var\">transition\u003C\u002Fspan>: \u003Cspan class=\"shj-num\">opacity\u003C\u002Fspan> \u003Cspan class=\"shj-num\">200\u003C\u002Fspan>ms, \u003Cspan class=\"shj-num\">transform\u003C\u002Fspan> \u003Cspan class=\"shj-num\">200\u003C\u002Fspan>ms, \u003Cspan class=\"shj-num\">display\u003C\u002Fspan> \u003Cspan class=\"shj-num\">200\u003C\u002Fspan>ms \u003Cspan class=\"shj-num\">allow-discrete\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n\u003Cspan class=\"shj-kwd\">dialog\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">open\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">opacity\u003C\u002Fspan>: \u003Cspan class=\"shj-num\">1\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-var\">transform\u003C\u002Fspan>: \u003Cspan class=\"shj-func\">scale\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">1\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\n\u003Cspan class=\"shj-kwd\">@starting\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">-style\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">dialog\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">[\u003C\u002Fspan>\u003Cspan class=\"shj-kwd\">open\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">]\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n    \u003Cspan class=\"shj-var\">opacity\u003C\u002Fspan>: \u003Cspan class=\"shj-num\">0\u003C\u002Fspan>;\n    \u003Cspan class=\"shj-var\">transform\u003C\u002Fspan>: \u003Cspan class=\"shj-func\">scale\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-num\">0.95\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003Cdiv>8\u003C\u002Fdiv>\u003Cdiv>9\u003C\u002Fdiv>\u003Cdiv>10\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'click'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>event\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> rect \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan> dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">getBoundingClientRect\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n  \u003Cspan class=\"shj-kwd\">const\u003C\u002Fspan> clickedOutside \u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\n    event\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>clientX \u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan> rect\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>left \u003Cspan class=\"shj-oper\">||\u003C\u002Fspan>\n    event\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>clientX \u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan> rect\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>right \u003Cspan class=\"shj-oper\">||\u003C\u002Fspan>\n    event\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>clientY \u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan> rect\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>top \u003Cspan class=\"shj-oper\">||\u003C\u002Fspan>\n    event\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>clientY \u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan> rect\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>bottom;\n\n  \u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>clickedOutside\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">close\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">confirmBtn\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'click'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">close\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'confirmed'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\ncancelBtn\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'click'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">close\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'cancelled'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\ndialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'close'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>returnValue \u003Cspan class=\"shj-oper\">===\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'confirmed'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-func\">deleteItem\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-html shj-multiline\" data-lang=\"html\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003Cdiv>4\u003C\u002Fdiv>\u003Cdiv>5\u003C\u002Fdiv>\u003Cdiv>6\u003C\u002Fdiv>\u003Cdiv>7\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">dialog\u003C\u002Fspan> \u003Cspan class=\"shj-class\">id\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"confirm-dialog\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">form\u003C\u002Fspan> \u003Cspan class=\"shj-class\">method\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"dialog\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">h2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>Delete item?\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">h2\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">button\u003C\u002Fspan> \u003Cspan class=\"shj-class\">value\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"cancelled\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>Cancel\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">button\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n    \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u003C\u002Fspan>\u003Cspan class=\"shj-var\">button\u003C\u002Fspan> \u003Cspan class=\"shj-class\">value\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">=\u003C\u002Fspan>\u003Cspan class=\"shj-str\">\"confirmed\"\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>Confirm\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">button\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n  \u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">form\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\n\u003Cspan class=\"shj-var\">\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&lt;\u002F\u003C\u002Fspan>\u003Cspan class=\"shj-var\">dialog\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">&gt;\u003C\u002Fspan>\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>","\u003Cdiv class=\"shj shj-lang-js shj-multiline\" data-lang=\"js\">\u003Cdiv class=\"shj-scroll\">\u003Cdiv class=\"shj-numbers\">\u003Cdiv>1\u003C\u002Fdiv>\u003Cdiv>2\u003C\u002Fdiv>\u003Cdiv>3\u003C\u002Fdiv>\u003C\u002Fdiv>\u003Cdiv class=\"shj-code\">dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>\u003Cspan class=\"shj-func\">addEventListener\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-str\">'close'\u003C\u002Fspan>\u003Cspan class=\"shj-oper\">,\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-kwd\">=&gt;\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">{\u003C\u002Fspan>\n  \u003Cspan class=\"shj-kwd\">if\u003C\u002Fspan> \u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>dialog\u003Cspan class=\"shj-oper\">.\u003C\u002Fspan>returnValue \u003Cspan class=\"shj-oper\">===\u003C\u002Fspan> \u003Cspan class=\"shj-str\">'confirmed'\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan> \u003Cspan class=\"shj-func\">deleteItem\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">(\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\n\u003Cspan class=\"shj-bracket\">}\u003C\u002Fspan>\u003Cspan class=\"shj-bracket\">)\u003C\u002Fspan>;\u003C\u002Fdiv>\u003C\u002Fdiv>\u003C\u002Fdiv>"]