UNPKG

@third774/google-font

Version:

A web component for loading fonts from Google Fonts

92 lines (81 loc) 2.38 kB
export class GoogleFont extends HTMLElement { // attributes to observe static get observedAttributes() { return ["family", "weight", "style", "display"]; } // attribute change callback attributeChangedCallback(name, oldValue, newValue) { if (oldValue !== newValue) { this.insertLinkTag(); } } render() { const template = document.createElement("template"); template.innerHTML = ` <style> :host { font-family: ${this.getAttribute("family") ?? "Inter"}; } </style> <slot></slot> `; this.shadowRoot!.innerHTML = ""; // append template content to shadow DOM this.shadowRoot!.appendChild(template.content.cloneNode(true)); } constructor() { super(); // attach shadow root this.attachShadow({ mode: "open" }); this.render(); } get href() { const family = (this.getAttribute("family") ?? "Inter").replace(/ /g, "+"); const weight = this.getAttribute("weight") ?? "400"; const weights = weight .split(",") .filter(Boolean) .map((w) => w.trim()); // might be null, normal, italic, oblique // we should assume normal if null const style = this.getAttribute("style") ?? "normal"; const display = this.getAttribute("display") ?? "fallback"; const styles = style .split(",") .filter(Boolean) .map((s) => s.trim()); const afterAtSymbol = weights .map((w) => styles.map((style) => { if (styles.length === 1 && style === "normal") { return w; } if (style === "normal") { return `0,${w}`; } if (style === "italic") { return `1,${w}`; } if (style === "oblique") { return `1,${w}`; } return `0,${w}`; }) ) .join(";"); const beforeAtSymbol = `${family}:${[ styles.includes("italic") && "ital", "wght", ] .filter(Boolean) .join(",")}`; // Asap:ital,wght@0,400;0,700;1,400;1,700 return `https://fonts.googleapis.com/css2?family=${beforeAtSymbol}@${afterAtSymbol}&display=${display}`; } insertLinkTag() { const link = document.createElement("link"); link.setAttribute("rel", "stylesheet"); link.setAttribute("href", this.href); document.head.appendChild(link); } }