GoogleChrome/dialog-polyfill: making the HTML dialog element work in older browsers
Polyfill for the HTML dialog element
At a glance
- What is it?
- A small JavaScript polyfill that emulates the native dialog element and form method="dialog", with a CSS file and a registration call. It works in IE9 and above, but it comes with a stacking context rule that decides whether it fits your layout.
- Who is it for?
- Adopt dialog-polyfill if you ship pages that still have to run on IE9 or other browsers without native dialog support, and if your dialog markup can live as a direct child of body. Do not adopt it if you only target browsers that already implement dialog, since the polyfill deliberately does not replace native support, or if your dialog must stay nested inside a component that creates a stacking context.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 90 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap dialog-polyfill fills, and who is still in it
The HTML dialog element gives a page a popup box, including a modal mode that makes the rest of the page inert while the box is open. The README describes the use case plainly: blocking interaction until the user answers or confirms something. Browsers that implement the element give you showModal, the ::backdrop pseudo-element and form method="dialog" for closing. Browsers that do not implement it give you an unknown element that renders inline and does nothing.
dialog-polyfill is for the second group. The README states it works on modern versions of all major browsers and supports IE9 and above. That support floor is the whole point: it is not a library for teams who want a nicer dialog API, it is a compatibility layer for teams whose support matrix still includes browsers from the IE9 era. If your analytics say every visitor runs a browser with native dialog support, this package adds a CSS file and a registration call for no benefit, because the polyfill does not replace native support.
What registerDialog does and how the fallback is wired
The mechanism is a single registration function rather than a class you instantiate. The README's steps are: include the CSS in the head, include the JS before you reference dialogPolyfill, create your dialog elements in the document, then call dialogPolyfill.registerDialog() passing one node at a time. After registration the README says the dialog always acts like a native dialog, and the example calls dialog.showModal() on the registered node.
That one-node-at-a-time detail matters in practice. There is no querySelectorAll convenience in the documented API, so a page with several dialogs needs a loop over the NodeList and a call per element. Registration is also the point where the polyfill decides what it is dealing with; the README is explicit that it will not replace native support, so on a modern browser the call is effectively a no-op and the native implementation stays in charge.
The backdrop is where the abstraction leaks. In a native dialog the backdrop is a pseudo-element, so you style dialog::backdrop. Under the polyfill the backdrop is an adjacent element in the DOM, so the selector becomes dialog + .backdrop. The README shows both rules side by side with the same background-color declaration, which is the pattern to copy if you want one visual result across both paths.
Installing dialog-polyfill and opening your first modal
The README gives npm as an optional install path, with the package name dialog-polyfill. The package.json confirms the published entry points: main is dist/dialog-polyfill.js and module is dist/dialog-polyfill.esm.js, both produced by a rollup build. There are three documented ways to load it: a script tag exposing a global dialogPolyfill, an ES module import, or a CommonJS require.
Start with the install:
npm install dialog-polyfillThe README's script global example is the shortest path to a working modal. It links the stylesheet in the head, places a dialog with a form method="dialog" inside the body, loads the UMD build, registers the element, and opens it. The form with an input of type submit is what closes the dialog, which is the form method="dialog" half of the polyfill's job.
<head>
<link rel="stylesheet" type="text/css" href="dist/dialog-polyfill.css" />
</head>
<body>
<dialog>
I'm a dialog!
<form method="dialog">
<input type="submit" value="Close" />
</form>
</dialog>
<script src="dist/dialog-polyfill.js"></script>
<script>
var dialog = document.querySelector('dialog');
dialogPolyfill.registerDialog(dialog);
dialog.showModal();
</script>
</body>After this runs, the dialog should appear as a modal box and the Close button should dismiss it. If you are bundling instead, the README shows an ESM import from the dist file or from the package name, and a CommonJS require for browserify-style builds:
import dialogPolyfill from 'dialog-polyfill'
// *OR*
const dialogPolyfill = require('dialog-polyfill')One more thing to copy from the README: if you want the dialog centered regardless of scroll position or stacking context, the polyfill CSS ships a helper class named fixed, applied as dialog class="fixed". The equivalent hand-written rule sets position to fixed, top to 50 percent and a translate on the Y axis.
The stacking context rule is the real constraint
The README calls the stacking context limitation the major one, and it is worth reading twice before you plan any integration work. Dialogs should not have parents that create a stacking context. The recommended fix is blunt: move the dialog element so it is a direct child of body. If that is not possible you may still be able to use the dialog, but the README lists two reasons to resolve it anyway. The polyfill cannot guarantee the dialog will be the top-most element on the page, and the dialog may be positioned incorrectly because it is positioned as part of the page layout where it is opened, not at a fixed point in the browser window.
That second point is the one that bites component-based front ends. A dialog declared inside a card, a modal wrapper or any element with a transform, filter or explicit z-index becomes part of that subtree's layout and paint order. The polyfill cannot hoist it out for you. The fixed helper class and the position fixed snippet are the documented workaround, but they change where the box sits rather than removing the stacking context problem.
The README also lists two smaller limitations. The browser's chrome may not always be reachable via the tab key, so keyboard users may not be able to tab out to browser UI while a modal is open. And changes to the CSS top or bottom values while the dialog is open are not retained. Neither is documented with a workaround. Shadow DOM gets a single sentence: it can work there, but it is not recommended.
Focus return is documented as your problem, not the polyfill's
The README's Extensions section notes that the WAI-ARIA guidance suggests returning focus to the previously focused element after a modal dialog closes, and then states that this is not part of the dialog spec itself. The project points to an external gist for adding the behavior, and notes that the snippet works even on the native dialog. In other words, the polyfill does not implement focus restoration, and the README does not pretend otherwise.
For an accessibility-tagged project this is the honest but incomplete part of the story. The topics list includes a11y, and the polyfill does give you a modal that makes the rest of the page inert, which is the core accessibility win over a hand-rolled div overlay. But focus return, and the tab-into-browser-chrome caveat above, are left to the integrator. If your test plan treats dialog accessibility as a checkbox the library provides, it will pass on the modal behavior and fail on focus management.
Where a native dialog or a full modal library fits better
The direct alternative is the native dialog element itself. The difference in approach is not cosmetic: native dialog gives you showModal, ::backdrop and form method="dialog" with no JavaScript payload, no registration loop and no stacking context rule, because the browser handles top-layer placement for you. The polyfill exists precisely because that behavior is missing in older browsers, so the choice between them is a support-matrix question, not a feature question. If your support floor excludes IE9-era browsers, the native element is the smaller and more predictable option.
A second alternative is a general modal or overlay library that builds its own DOM, its own focus trap and its own positioning. Those libraries typically do not depend on the browser implementing dialog, so they behave the same everywhere, and they usually handle focus return because they own the whole lifecycle. The trade-off is weight and a non-standard API: you are adopting a component rather than polyfilling a standard element, and your markup stops being portable to the native element later. dialog-polyfill's advantage is that the markup you write today is the markup the platform wants tomorrow.
Maintenance, licence and what an upgrade costs
The last push to the default branch was on 2026-07-02, and the repository is not archived. The most recent tagged release listed is v0.5.6 from 2021-01-11, with v0.5.4 and v0.5.3 in 2020. So the release history is quiet even though the branch has seen recent activity. For a compatibility polyfill that is not automatically a problem, since the target is a frozen set of old browsers, but it does mean you should not expect new features and should treat the published version as the contract.
The package.json declares the licence as BSD and the repository metadata identifies it as BSD-3-Clause. That is a permissive licence, which matters here because a polyfill is code you ship to end users, not a build-time tool. If you fork it to patch the stacking context behavior for your layout, the licence terms travel with the fork; check the LICENSE file in the repository for the exact text rather than relying on the package metadata field.
Upgrade cost is low by design. The build is rollup producing UMD and ESM bundles, and the CSS is a straight copy from dialog-polyfill.css into dist. The package exposes index.d.ts, so TypeScript consumers get types for registerDialog. There is no runtime dependency to reconcile, and no configuration file to migrate. The real upgrade risk is behavioural: a change to how the backdrop element is inserted would break any dialog + .backdrop rule you wrote, so pin the version and re-check your backdrop styling when you move.
Editorial conclusion
Adopt dialog-polyfill if you ship pages that still have to run on IE9 or other browsers without native dialog support, and if your dialog markup can live as a direct child of body. Do not adopt it if you only target browsers that already implement dialog, since the polyfill deliberately does not replace native support, or if your dialog must stay nested inside a component that creates a stacking context. Before committing, open test.html from the repository in the oldest browser you support and confirm the dialog centers and traps the tab order the way your page needs.
Frequently asked questions
What is a polyfill in JavaScript, and what does dialog-polyfill polyfill?
A polyfill is code that supplies a browser feature to browsers that lack it. dialog-polyfill supplies the dialog element and form method="dialog", which the README says it supports down to IE9.
What is the purpose of polyfills?
They let a page use a standard feature even when the browser does not implement it. In this project's case, the README states the polyfill does not replace native support, so modern browsers keep their built-in dialog behavior.
What is a dialog?
The README describes dialog as an element for a popup box in a web page, with a modal option that makes the rest of the page inert while it is open. That modal mode is what dialog-polyfill emulates on older browsers.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/googlechrome-dialog-polyfill)