STRML / textFit

A jQuery-free component that quickly fits single and multi-line text to the width (and optionally height) of its container.
https://textfit.strml.net
637 stars 123 forks source link

Invalid scaling caused by inconsistency between innerspan.scrollWidth and el.clientWidth #49

Open Mat-thieu opened 3 years ago

Mat-thieu commented 3 years ago

Hi there, I've got an interesting one for you here, with a PR on the way!

To recreate for this specific jsfiddle ( https://jsfiddle.net/y6xej9kv/2/ ) , you need to be on Windows + Chrome, set your OS-level display scaling to 175% (display settings), then in your browser, zoom to 67%. I'm sorry it's a bit obscure but this is how it's recreated for that specific sample. Any OS, on Chrome zoom to 75% When all this is done you will see this: Bug sample but we're actually expecting this: Bug sample and this is likely what you will see if you open the "bugged" jsfiddle without any of the scaling/zoom settings anyway.

So what's going on here is that as soon as you mess around with scaling, some dimensions will fall on floating points, but textfit is using scrollWidth and clientWidth to determine dimensions, which are not only always pure integers, but also rounded differently internally by the browser, which is the root cause of this bug.

If you're running the "bugged" JSfiddle with the settings I mentioned, these will be the values

invalid values Meaning that the while loop that determines the fitted size can never fulfill correctly.

There are a couple ways to solve this, but in the PR ( fiddle example here https://jsfiddle.net/wh6q7yxb/1/ )I'll opt for replacing both clientWidth and scrollWidth (also clientHeight and scrollHeight to prevent a similar issue) with .getBoundingClientRect() which will always return the exact rendered values as a float. I understand .getBoundingClientRect is not the same as .scrollHeight/width, I don't think using that property there is actually not of much use, because it's a span, by default these can't scroll in any direction so only if someone explicitly made a display: block; out of it can this be a issue.

STRML commented 3 years ago

Pretty interesting! Zoom levels and float dimensions have always been a thorn in web developers' collective sides. Looking forward to the PR.