Last active
December 15, 2025 16:57
-
-
Save adactio/a445544723363d37b9c31a74a03ef928 to your computer and use it in GitHub Desktop.
Web Install HTML web component
Author
That querySelector will only get a <button> when the Web Component is defined after (light)DOM parsed.
When defined before lightDOM is parsed; ie. in the <head> (to prevent those FOUC issues) querySelector will return null
Because the connectedCallback runs on the opening tag (before lightDOM is parsed),
you need to wait a tick before querying the lightDOM.
I made it a (HTML) Web Component, so it also works when its not a HTML Web Component (user added <button>)
<script>
customElements.define('button-install', class extends HTMLElement {
connectedCallback() {
setTimeout(() => { // wait till lightDOM is parsed
let canInstall = navigator.install && !window.matchMedia('(display-mode: standalone)').matches;
canInstall = true; // for testing
if (canInstall) {
// use existing button or create new button
let button = this.querySelector("button") || document.createElement('button');
// append will 'move' existing button, required to create new button
this.append(Object.assign(button, {
textContent: button.textContent || "Install this App!", // not overwrite user button label
// only attaching one listener, event property handler will do
onclick: async _ => await navigator.install()
}));
} else {
// this.innerHTML = ""; // clear lightDOM content
this.remove(); // remove <button-install> entirely
}
});
}
});
console.log('installable?', navigator.install, window.matchMedia('(display-mode: standalone)').matches);
</script>
<button-install>
<button>Install the App!</button>
</button-install>
<button-install></button-install>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage:
<install-button> <button>Add the app</button> </install-button>