block by tophtucker 62f93a4658387bb61e4510c37e2e97cf

Measure text

Full Screen

To approximate the width of strings without touching the DOM. (Or rather: getBoundingClientRect is used to calibrate a static function.) Choose a font-family upfront; font-size can be passed as a parameter.

Calibration script seems to suck in Firefox… but the generated calibrated function should work fine in Firefox!

Instructions

  1. Run your finger across the smooth depressed rectangle below your keyboard until the tailed triangle on your screen appears over the rectangle with the word ‘helvetica’ in the upper right of the window above (beside “font-family:”)
  2. Press your finger, hard, into the smooth rectangle
  3. Strike a key; repeat until the name of your desired font appears
  4. Stroke the smooth rectangle left-to-right until the tailed triangle appears over the small ‘Go’ in the other rectangle
  5. Apply pressure to your finger until you feel a click
  6. Run finger across smooth rectangle top-to-bottom until tailed triangle appears inside box below “Copy and paste me:”
  7. Again press finger down (i.e. toward ground, not toward self) and release
  8. Depress the “command” button on your keyboard and hold it there, then depress the “c” button, then release both

Helvetica default version

function measureText(string, fontSize = 10) {
  const widths = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2796875,0.2765625,0.3546875,0.5546875,0.5546875,0.8890625,0.665625,0.190625,0.3328125,0.3328125,0.3890625,0.5828125,0.2765625,0.3328125,0.2765625,0.3015625,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.2765625,0.2765625,0.584375,0.5828125,0.584375,0.5546875,1.0140625,0.665625,0.665625,0.721875,0.721875,0.665625,0.609375,0.7765625,0.721875,0.2765625,0.5,0.665625,0.5546875,0.8328125,0.721875,0.7765625,0.665625,0.7765625,0.721875,0.665625,0.609375,0.721875,0.665625,0.94375,0.665625,0.665625,0.609375,0.2765625,0.3546875,0.2765625,0.4765625,0.5546875,0.3328125,0.5546875,0.5546875,0.5,0.5546875,0.5546875,0.2765625,0.5546875,0.5546875,0.221875,0.240625,0.5,0.221875,0.8328125,0.5546875,0.5546875,0.5546875,0.5546875,0.3328125,0.5,0.2765625,0.5546875,0.5,0.721875,0.5,0.5,0.5,0.3546875,0.259375,0.353125,0.5890625]
  const avg = 0.5279276315789471
  return string
    .split('')
    .map(c => c.charCodeAt(0) < widths.length ? widths[c.charCodeAt(0)] : avg)
    .reduce((cur, acc) => acc + cur) * fontSize
}

Backstory

So we have this chart in React and we want the right axis to autosize to fit labels of varying length. One solution is to render the whole axis, get its bounding box, and then re-render the whole chart with the computer axis width as a margin parameter. But that sorta sucks because you double your render cycles (or fracture your render code in weird unreadable ways, with un-React-like DOM manipulation).

This solution is fragile and hacky in other ways, but may be perfectly suitable in many cases: just do the math with hardcoded character widths! Sorry! The measureText function here is calibrated once to a font (by you! manually! by default, Helvetica, natch) and then takes a string and font size and returns the computed rendered width. Just copy and paste the measureText function into your project.

Obviously assumes no kerning, no ligatures, no wrapping, etc. Only supports ASCII; otherwise it assumes a default average character width. It’s also missing a lot of weird thin spaces and such.

This has surely been done a million times (including by my coworker it turns out lol), there’s stuff like adambisek/string-pixel-width, but I couldn’t quickly find something quick & easy & copypastable.

Good night.

index.html

calibrate.js

demo.js

style.css