Skip to content

Instantly share code, notes, and snippets.

@acip
Last active April 16, 2020 07:20
Show Gist options
  • Save acip/33527b88cdbc33a7e828d19e34f13f45 to your computer and use it in GitHub Desktop.
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
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