Last active
April 16, 2020 07:20
-
-
Save acip/33527b88cdbc33a7e828d19e34f13f45 to your computer and use it in GitHub Desktop.
Fit the text into element by adjusting the font size across multiple elements. In action here https://repl.it/repls/CumbersomeVisibleSpellchecker
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const buttons = document.querySelectorAll('button'); | |
fitTextToElementsGroup(buttons); | |
function fitTextToElementsGroup(elements) { | |
const arrElements = elements.map ? elements : Array.apply(null, elements); | |
const fontSizes = arrElements.map(computeMaxFontSize); | |
const minFontSize = Math.min.apply(Math, fontSizes); | |
applyFontSizePx(buttons, minFontSize); | |
function applyFontSizePx(elements, fontSize) { | |
elements.forEach(function(el) { | |
el.style.fontSize = fontSize + 'px'; | |
}); | |
} | |
// assumes that the content of the el is text only (no other sub elements) | |
// assumes font size is expressed in px | |
function computeMaxFontSize(el, options) { | |
// options | |
const minFontSize = options.minFontSize || 10; | |
const step = options.step || 3; | |
const computedStyle = window.getComputedStyle(el); | |
const horizontalPadding = parseInt(computedStyle.getPropertyValue('padding-left'), 10) + parseInt(computedStyle.getPropertyValue('padding-right'), 10); | |
const witdthToFitText = el.clientWidth - horizontalPadding; | |
const initialFontSize = parseInt(computedStyle.getPropertyValue('font-size'), 10); | |
const shouldDownSize = () => el.children[0].clientWidth > witdthToFitText; | |
// append a span so we can properly get size of the text (inline block is required for the element to have a box) | |
el.innerHTML = '<span style="display:inline-block;padding:0;margin:0;border:0;outline:0">' + el.textContent + '</span>'; | |
if (!shouldDownSize()) { | |
return initialFontSize; | |
} | |
var fontSize = initialFontSize; | |
// decrease the font size until it fits or min font size reached | |
while (shouldDownSize() && fontSize > minFontSize) { | |
fontSize = fontSize - step; | |
el.style.fontSize = fontSize + 'px'; | |
} | |
// restore the content of the element | |
el.innerHTML = el.textContent; | |
el.style.fontSize = initialFontSize + 'px'; | |
return fontSize; | |
} | |
} | |
// fit text of the text to fit the element | |
// optimized for one element only | |
function fitTextToElement(el, options) { | |
// options | |
const minFontSize = options.minFontSize || 10; | |
const step = options.step || 1; | |
const computedStyle = window.getComputedStyle(el); | |
const horizontalPadding = parseInt(computedStyle.getPropertyValue('padding-left'), 10) + parseInt(computedStyle.getPropertyValue('padding-right'), 10); | |
const witdhtToFitText = el.clientWidth - horizontalPadding; | |
const initialFontSize = parseInt(computedStyle.getPropertyValue('font-size'), 10); | |
const shouldDownSize = () => el.children[0].clientWidth > witdhtToFitText; | |
// append a span so we can properly get size of the text (inline block is required for the element to have a box) | |
el.innerHTML = '<span style="display:inline-block;padding:0;margin:0;border:0;outline:0">' + el.innerText + '</span>'; | |
if (!shouldDownSize()) { | |
return initialFontSize; | |
} | |
var fontSize = initialFontSize; | |
// decrease the font size until it fits or min font size reached | |
while (shouldDownSize() && fontSize > minFontSize) { | |
fontSize = fontSize - step; | |
el.style.fontSize = fontSize + 'px'; | |
} | |
// restore the content of the element | |
el.innerHTML = el.innerText; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment