Back to Overview

Measuring SVG Text Width in Deno

3 days ago

A guide to getting the text width in SVG using Deno.

Deno
SVG

The challenge (no canvas in Deno) and why you'd care about SVG text measurement

While building a serverless SVG badge generator in Deno, I ran into a fun challenge: how do you measure the width of text in an SVG, when Deno doesn’t support Canvas?

The badges show browser compatibility info as inline SVG images.
To layout the badge properly, I needed to calculate how wide the label would be.
Unfortunately, SVG doesn't have a layout engine, and Deno doesn't have a native CanvasRenderingContext2D (see issue).

One thing that complicated this even more, was that i was using a custom font, so I needed to measure the text width with that specific font in mind. \

Failed Starts & the Solution

I first explored canvas polyfills like canvaskit, which exposes a Skia-backed Canvas API in Deno via WebAssembly.
It worked—but even after loading the font, measurements were off by a few pixels.

Then I found text-to-svg, a library that parses fonts and calculates dimensions directly from glyph metrics, no canvas needed.
This also makes it way more lightweight than a full canvas polyfill, which is great for serverless environments.
So after some tests I settled on it as the best solution to measure text width in SVG.
Here's how I implemented it:

ts
import text2svg from "npm:text-to-svg";

const textSvg = text2svg.loadSync("Roboto.otf");

export function getTextSize(
  text: string,
  fontSize = 16,
  fontFamily = "Roboto"
): { width: number; height: number } {
  const metrics = textSvg.getMetrics(text, {
    x: 0,
    y: 0,
    fontSize,
    fontFamily,
    anchor: "top",
    attributes: { fill: "black" },
  });

  return {
    width: metrics.width,
    height: metrics.height,
  };
}

getTextSize("Hello", 16);
// => { width: 42.12, height: 18.0 }

I converted my font to otf, but any of OTF, TTF and WOFF should work too.

Final Thoughts

If you’re working with SVG in Deno and need to measure text size, you should really try out text-to-svg.