Skip to content

Instantly share code, notes, and snippets.

@MarioSo
Created September 24, 2018 17:35
Show Gist options
  • Select an option

  • Save MarioSo/ffff74125486c5ab251f9e9cded3e9eb to your computer and use it in GitHub Desktop.

Select an option

Save MarioSo/ffff74125486c5ab251f9e9cded3e9eb to your computer and use it in GitHub Desktop.
resizes text to match given horizontal boundaries
/**
* resizeText
* by Mario Sommer <mariosommer.at>
*
* based on Jeremy Apthorp's approach - thanks Jeremy
* improved performance by using binary seach algorithm to find font size
*/
export const resizeText = (el, opts = {}) => {
if (!opts.width && !opts.height) {
console.error('Must specify a size to resize the text into!')
return
}
const fitsInContainer = (element, width, height) => {
return element.offsetWidth < width && element.offsetHeight < height
}
const binarySearch = (start, stop, el, width, height) => {
const newSize = Math.floor(start + (stop - start) / 2)
if (newSize === start) return newSize
el.style.fontSize = `${newSize}px`
if (fitsInContainer(el, width, height)) {
if (debug) console.log('up', newSize, stop)
return binarySearch(newSize, stop, el, width, height)
}
if (debug) console.log('down', start, newSize)
return binarySearch(start, newSize, el, width, height)
}
let size = opts.minSize || 8
let p = el.style.position
el.style.position = 'absolute'
el.style.fontSize = '1px'
opts.width -= 1
while (el.offsetWidth < opts.width && size < 2048) {
size *= 2
el.style.fontSize = size + 'px'
}
const finalSize = binarySearch(size / 2, size, el, opts.width, opts.height)
// Without smacking the layout, sometimes the text will leave a scrollbar in
// the window, which changes the width/height.
el.style.fontSize = '1px'
// Force a relayout.
el.offsetHeight
// Be 1px smaller than the size which exceeded the given rect.
el.style.fontSize = finalSize - 1 + 'px'
el.style.position = p
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment