FitText makes font-sizes flexible. Use this plugin script on your fluid or responsive layout to achieve scalable headlines that fill the width of a parent element.
- This javascript was originally a jQuery plugin by Dave Rupert
- This version with vanilla javascript by Remy Sharp, he writes about it here
- Video of the talk
If you have a small site and don't want to attach jQuery, just attach fittext-remy.js and put this just before </body> (fittext1 is an header id).
<script>
window.fitText(document.getElementById('fittext1'));
</script>From: I know jQuery. Now what?
I was working on a project recently, and knew of the fitText.js project. I went to drop it in, but then spotted that it needed jQuery.
Hmm. Why?
It uses the following jQuery methods:
- .extend
- .each
- .width
- .css
- .on (and not with much thought to performance)
The plugin is this:
$.fn.fitText = function( kompressor, options ) {
// Setup options
var compressor = kompressor || 1,
settings = $.extend({
'minFontSize' : Number.NEGATIVE_INFINITY,
'maxFontSize' : Number.POSITIVE_INFINITY
}, options);
return this.each(function(){
// Store the object
var $this = $(this);
// Resizer() resizes items based on the object width divided by the compressor * 10
var resizer = function () {
$this.css('font-size', Math.max(Math.min($this.width() / (compressor*10), parseFloat(settings.maxFontSize)), parseFloat(settings.minFontSize)));
};
// Call once to set.
resizer();
// Call on resize. Opera debounces their resize by default.
$(window).on('resize orientationchange', resizer);
});
};.extend is being used against an object that only has two options, so I would rewrite to read:
if (options === undefined) options = {};
if (options.minFontSize === undefined) options.minFontSize = Number.NEGATIVE_INFINITY;
if (options.maxFontSize === undefined) options.maxFontSize = Number.POSITIVE_INFINITY;return this.each used to loop over the nodes. Let’s assume we want this code to work stand alone, then our fitText function would receive the list of nodes (since we wouldn’t be chaining):
var length = nodes.length,
i = 0;
// would like to use [].forEach.call, but no IE8 support
for (; i < length; i++) {
(function (node) {
// where we used `this`, we now use `node`
// ...
})(nodes[i]);
}$this.width() gets the width of the container for the resizing of the text. So we need to get the computed styles and grab the width:
// Resizer() resizes items based on the object width divided by the compressor * 10
var resizer = function () {
var width = node.clientWidth;
// ...
};It’s really important to note that swapping .width() for .clientWidth will not work in all plugins. It just happen to be the right swap for this particular problem that I was solving (which repeats my point: use the right tool for the job).
$this.css is used as a setter, so that’s just a case of setting the style:
node.style.fontSize = Math.max(...);$(window).on('resize', resizer) is a case of attaching the event handler (note that you’d want addEvent too for IE8 support):
window.addEventListener('resize', resizer, false);In fact, I’d go further and store the resizers in an array, and on resize, loop through the array executing the resizer functions.
Sure, it’s a little more work, but it would also easy to upgrade this change to patch in jQuery plugin support as an upgrade, rather than making it a prerequisite.
Rant will be soon over: it also irks me when I see a polyfill requires jQuery – but I know the counter argument to that is that jQuery has extremely high penetration so it’s possibly able to justify the dependency.
- Thanks to Trent, Dave and Reagan for original FitText.js http://fittextjs.com/
- Thanks to Remy Sharp for the javascript used in the demo here on Github
- Thanks to Jeremy Keith for the convenient repo this was cloned from, one can see his example demo here