Skip to content

Instantly share code, notes, and snippets.

@andrioid
Last active June 11, 2025 09:11
Show Gist options
  • Select an option

  • Save andrioid/2fbc52d5a0e72c8cfbee5d273df087ee to your computer and use it in GitHub Desktop.

Select an option

Save andrioid/2fbc52d5a0e72c8cfbee5d273df087ee to your computer and use it in GitHub Desktop.
svg-icon.mjs
/**
* Usage, import as module and use like <svg-icon href="/icons/icon.svg#icon></svg-icon>.
* Note: Due to browser quirks, the icon file requires a top-level id for the fragment. Otherwise it wont work in Firefox.
*/
class IconElement extends HTMLElement {
constructor() {
super();
this._href = ""
}
static get observedAttributes() {
return ['href'];
}
// lucide question mark document
defaultIcon = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 17h.01M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7z"/><path d="M9.1 9a3 3 0 0 1 5.82 1c0 2-3 3-3 3"/></g></svg>`
connectedCallback() {
this._href = this.getAttribute('href') ?? ""
this.render()
}
attributeChangedCallback(name, oldVal, newVal) {
if (oldVal === newVal) return
switch (name) {
case 'href':
if (typeof newVal === "string" && !newVal.match(/#.*$/)) {
console.warn("svg-icon cannot render. 'href' must include a fragment (e.g. icon.svg#icon) and it must exist inside your icon")
console.debug("Firefox does not support root element references")
this._href = "";
this.render()
return;
}
this._href = newVal
this.render()
break;
}
}
render() {
let rendering = `<svg height="1em" viewbox="0 0 24 24">`
if (this._href !== "") {
rendering += `<use width="100%" height="100%" href="${this._href}"></use>`
} else {
rendering += this.defaultIcon
}
rendering += `</svg>`
this.innerHTML = rendering;
}
}
customElements.define("svg-icon", IconElement)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment