Skip to content

Instantly share code, notes, and snippets.

@tak-dcxi
Created August 31, 2025 17:25
Show Gist options
  • Select an option

  • Save tak-dcxi/38a45b765969fcf2c790827c5564cbe7 to your computer and use it in GitHub Desktop.

Select an option

Save tak-dcxi/38a45b765969fcf2c790827c5564cbe7 to your computer and use it in GitHub Desktop.
Fit Text
fit-text {
display: block flow;
&::part(svg) {
display: block flow;
inline-size: 100%;
block-size: auto;
}
&::part(text) {
fill: currentcolor;
}
&:not(:defined) {
visibility: hidden;
}
}
class FitTextElement extends HTMLElement {
private shadow: ShadowRoot;
private svg: SVGSVGElement;
private textElement: SVGTextElement;
private observer: ResizeObserver | null = null;
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
this.shadow.innerHTML = `
<svg part="svg">
<text part="text" dominant-baseline="text-before-edge"></text>
</svg>
`;
this.svg = this.shadow.querySelector("svg")!;
this.textElement = this.shadow.querySelector("text")!;
}
connectedCallback(): void {
this.updateText();
this.setupObserver();
this.observeTextChanges();
}
disconnectedCallback(): void {
this.observer?.disconnect();
}
private updateText(): void {
this.textElement.textContent = this.textContent;
this.updateViewBox();
}
private updateViewBox(): void {
requestAnimationFrame(() => {
const bbox = this.textElement.getBBox();
const newViewBox = `${bbox.x} ${bbox.y} ${bbox.width} ${bbox.height}`;
const currentViewBox = this.svg.getAttribute("viewBox");
if (currentViewBox === newViewBox) return;
this.svg.setAttribute("viewBox", newViewBox);
});
}
private setupObserver(): void {
this.observer = new ResizeObserver(() => {
requestAnimationFrame(() => {
this.updateViewBox();
});
});
this.observer.observe(this);
}
private observeTextChanges(): void {
const textObserver = new MutationObserver(() => {
this.updateText();
});
textObserver.observe(this, {
childList: true,
characterData: true,
subtree: true
});
}
}
customElements.define("fit-text", FitTextElement);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment