calculate-size

Measures the rendered pixel width and height of a text string using a hidden DOM element, with built-in result caching.

Library
npm
v1.1.1
121stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
33/100Needs Attention
Development Activity0
Maintenance0
Community60
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
40/100Fair
Architecture65
Code Quality42
Innovation28
Learning Curve25

calculate-size is a small TypeScript utility that answers a narrow but recurring browser question: how many pixels will this string take up once it’s rendered in a given font? It works by creating an offscreen, absolutely-positioned div with the requested font family, size, weight, line height, and optional width constraint, inserting the text as a text node, reading back offsetWidth/offsetHeight, and then removing the element from the DOM.

Because layout measurement can be relatively expensive when called repeatedly (for example inside a render loop or a canvas-sizing routine), the library memoizes results in a module-level cache keyed on the JSON-serialized text and options, so identical calls after the first are just an object lookup. The entire implementation is a single exported function with two small private helpers, and it ships its own TypeScript type declarations out of the box.

What You Get

  • A single default-exported calculateSize(text, options) function returning { width, height } in pixels
  • Support for font, fontSize, fontWeight, lineHeight, width (to constrain wrapping), and wordBreak options
  • Automatic in-memory caching of results keyed by text + options, so repeat calls skip DOM work entirely
  • Bundled TypeScript type declarations (OptionalOptions, Size) with no separate @types package needed
  • Zero runtime dependencies — the whole library is one small compiled file

Common Use Cases

  • Sizing a canvas or SVG <text> element to fit a dynamically generated string before drawing it
  • Auto-resizing an input, tooltip, or badge so it never clips the text it contains
  • Pre-computing label widths for a chart or diagram layout engine that needs pixel dimensions ahead of render
  • Deciding whether a string needs to be truncated/ellipsized based on its measured width against an available container size

Under The Hood

Architecture The entire library lives in one file, src/index.ts, with no classes or dependency injection: a default-exported function calculateSize(text, options), two small private helpers (createDummyElement, destroyElement), and a single module-level cache object. The flow is linear — merge the passed options with hardcoded defaults, build a cache key by JSON-stringifying {text, options}, return early on a cache hit, otherwise create a hidden absolutely-positioned div styled with the requested font properties, append it to document.body, read offsetWidth/offsetHeight, remove the element, store the result in the cache, and return it. The one structural risk is that the cache is a plain object with no eviction or size cap, so a caller that generates many unique text/option combinations over a long-lived page session would grow it unbounded — a change to the core abstraction (the cache) is the only thing that could meaningfully alter behavior here.

Tech Stack Written in TypeScript (targeting the tsc compiler configured in tsconfig.json) with zero runtime dependencies — package.json declares no dependencies entries at all. The devDependencies are all test/build tooling: typescript for compilation to the published lib/ output, and ava, express, and nightmare used together to run the test suite (Express serves a static test page, Nightmare drives a real headless browser via Electron to execute the library inside an actual DOM, and Ava is the assertion runner). There is no bundler and no framework dependency — this is a plain DOM-manipulation utility meant to run in any real browser environment.

Code Quality Tests exist in test/index.js and take an integration-style approach appropriate for a DOM-measurement library: rather than mocking the DOM, they spin up an Express static server and drive an actual browser instance (via Nightmare/Electron) to call calculateSize against real rendered text, asserting exact pixel width/height across font, size, weight, and width-constraint variations. This is a reasonable strategy for something whose whole job is browser layout output, but it is also brittle — pixel-perfect assertions depend on the exact font-rendering environment of the test runner, and the tooling itself (Nightmare/Electron circa 2016) has been unmaintained for years, so these tests are unlikely to still run on a current Node/Electron toolchain. There’s no linter configuration and no active CI beyond a stale .travis.yml. The source itself has no explicit error handling — options is mutated in place rather than copied, and the cache has no eviction — but naming is clear and the surface area is small enough that this rarely matters in practice.

What Makes It Unique The core technique — measuring text by temporarily rendering it in a hidden, off-screen DOM element and reading back its layout box — is a well-known browser pattern, not something original to this library. What calculate-size adds on top is convenience: a small, dependency-free, typed wrapper around that pattern with automatic result memoization, so callers don’t have to hand-roll the hidden-element dance or worry about redundant DOM churn for repeated measurements of the same string.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search