Skip to content
Learn Netverks
0

Why is there a difference when measuring words in an HTML page, vs. measuring their individual letters?

asked 9 hours ago by @qa-n2jt5nc3kjw2jk1fwito 0 rep · 30 views

javascript html html5 canvas

I'm trying something with similar goals as the Knuth-Plass linebreaking algorithm. (However, no offering on the market will work for my use case - and I don't want the overhead of a library anyhow.)

When I measure the entire word rendered into a div, I'm getting a different width than when I measure the individual letters and add those values up.
Same font. Same fontsize.

The discrepancy is not uniform, per character, per word.

It's ranged from 0.00001, all the way up to 0.59 pixels, in the samples I've compared so far.

I could deal with as much as +/- 0.01.

A discrepancy as large as I'm seeing is going to stack - and it /will/ affect the ultimate outcome, as half a pixel across even 10-15 words could mean the difference of an unnecessary line break. Average discrepancy is about 0.25 pixels.

As best I can tell there's nothing wrong with my code.
I suspect some hidden quirk of HTML or how browsers handle text.
(I don't see how posting the several hundred lines used to derive thus far will help.)

I've been mainly using getBoundingClientRects() in JS, though I did try HTML5 canvas, also. Same result, with very minor discrepancy between the two methods - more in the range of deviation I'm looking for - 5-6 zeroes after the decimal.

Does anybody know what I'm missing?

Comments on this question (0)

Use comments to ask for clarification — answers go in the answer box below.

Log in to comment on this question.

3 answers

1

You did not mention kerning, so possibly you missed on that.

[...] kerning is the process of adjusting the space between two specific characters, or letterforms, in a font. It is not to be confused with tracking, by which spacing is adjusted uniformly over a range of characters.

Wikipedia - Kerning

To illustrate, check the image from Wikipedia. This would also explain why you do not see a consistent effect but varying results:

To verify this as the reason, you could try to disable kerning via font-kerning and compare the results then:

body {
  font-kerning: none;
}

Jordan Diaz · 0 rep · 9 hours ago

0

It would be a lot easier to see if you've missed anything if you could edit your question to share the code you're currently using

Dev Hayes · 0 rep · 9 hours ago

0
  ctx.fontKerning = "none";

That's an acceptable margin! Can't believe I forgot about kerning, haha.
Been a while since I messed with stuff like this.
Thanks a million!

Drew Morris · 0 rep · 9 hours ago

Your answer