Last active
August 29, 2015 13:56
-
-
Save imbcmdth/8895128 to your computer and use it in GitHub Desktop.
resize text inside of a block level element to be as large as possible while still fitting completely inside another div without overflow
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
(function (root, factory) { | |
if (typeof exports === 'object') { | |
module.exports = factory(require('masala')); | |
} else if (typeof define === 'function' && define.amd) { | |
define(['masala'], factory); | |
} else { | |
root.fitText = factory(root.masala); | |
} | |
}(this, function (masala) { | |
var rectEnum = { | |
'tooLarge': 1, | |
'tooSmall': 2, | |
'justRight': 3 | |
}; | |
function compareRectangles (config) { | |
var outerRect = config.parent.getBoundingClientRect(), | |
outerHeight = outerRect.height, | |
outerWidth = outerRect.width; | |
var innerRect = config.wrapper.getBoundingClientRect(), | |
innerHeight = innerRect.height, | |
innerWidth = innerRect.width; | |
if (innerHeight > outerHeight || innerWidth > outerWidth) { | |
return rectEnum.tooLarge; | |
} else if (innerHeight < outerHeight || innerWidth < outerWidth) { | |
return rectEnum.tooSmall; | |
} else { | |
return rectEnum.justRight; | |
} | |
} | |
function roundedAverage(a, b, scale) { | |
return Math.round(scale * (a + b) / 2) / scale; | |
} | |
// Perform binary search for the best font-size | |
function findBestFontSize (config, bestSize) { | |
var midSize = roundedAverage(config.minSize, config.maxSize, config.scale), | |
limitReached = config.minSize >= midSize || midSize >= config.maxSize; | |
config.wrapper.style.fontSize = midSize + config.units; | |
var rectSize = compareRectangles(config); | |
if (rectSize === rectEnum.tooLarge) { | |
if (limitReached) { | |
return bestSize; | |
} else { | |
config.maxSize = midSize; | |
return findBestFontSize(config, bestSize); | |
} | |
} else if (rectSize === rectEnum.tooSmall) { | |
if (limitReached) { | |
return Math.max(midSize, bestSize); | |
} else { | |
config.minSize = midSize; | |
return findBestFontSize(config, midSize); | |
} | |
} else { | |
return midSize; | |
} | |
} | |
function getWrapper (element) { | |
// if it exists, just get it and return it | |
var wrap = element.querySelector('.fit-text-wrapper'); | |
if (wrap) { | |
return wrap; | |
} | |
// otherwise we have to create it | |
wrap = document.createElement('div'); | |
wrap.className = 'fit-text-wrapper'; | |
while (element.childNodes.length) { | |
wrap.appendChild(element.childNodes[0]); | |
} | |
element.appendChild(wrap); | |
return wrap; | |
} | |
function parseNumber(num, defaultNum) { | |
var parsedNum = parseFloat(num); | |
return isNaN(parsedNum) | |
? defaultNum | |
: parsedNum; | |
} | |
function fitTextBase (options) { | |
var config = {}; | |
if (options.fillParent) { | |
config.parent = options.element.parentNode; | |
config.wrapper = options.element; | |
} else { | |
config.parent = options.element; | |
config.wrapper = getWrapper(parent); | |
} | |
config.scale = Math.pow(10, parseNumber(options.precision, 0)); | |
config.units = options.units || 'px'; | |
config.minSize = parseNumber(options.minimumSize, 0); | |
config.maxSize = parseNumber(options.maximumSize, 100); | |
var bestSize = findBestFontSize(Object.create(config), config.minSize); | |
config.wrapper.style.fontSize = bestSize + options.units; | |
} | |
// Set some defaults for the options-object and make `element` required and return the final function | |
return masala(fitTextBase, { | |
element: null, | |
minimumSize: 0, | |
maximumSize: 100, | |
precision: 2, | |
units: "px", | |
fillParent: false | |
}); | |
})); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment