Fit title to div

Fits text by scaling font to a div with a fixed width and, most importantly, height.

by b9chris

HTML

<button>Resize</button>

<div class=event>RED</div>
<div class=event>Reasonably long thing</div>
<div class=event>Unreasonably, super long ridiculous maximum overdrive family event time home weightless edition thing</div>
<div class=event>Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really? Really?</div>

<div id=output></div>

CSS

body {
    font: 10pt Verdana;
}

div.event {
    /* height MUST be set for this to work! */
    width: 300px; height: 100px;
    background: #eee;
    margin: 0 0 5px 0;
}

JavaScript

(function($, undefined) {
	function resizeLoop(testTag, checkSize) {
		var fontSize = 10;
		var min = 10;
		var max = 0;
		var exceeded = false;
		
		for(var i = 0; i < 30; i++) {
			testTag.css('font-size', fontSize);
			if (checkSize(testTag)) {
				max = fontSize;
				fontSize = (fontSize + min) / 2;
			} else {
				if (max == 0) {
					// Start by growing exponentially
					min = fontSize;
					fontSize *= 2;
				} else {
					// If we're within 1px of max anyway, call it a day
					if (max - fontSize < 2)
						break;
					
					// If we've seen a max, move half way to it
					min = fontSize;
					fontSize = (fontSize + max) / 2;
				}
			}
		}
		
		return fontSize;
	}
	
	function sizeText(tag) {
		var width = tag.width();
		var height = tag.height();

        // Clone original tag and append to the same place so we keep its original styles, especially font
		var testTag = tag.clone(true)
		.appendTo(tag.parent())
		.css({
			position: 'absolute',
			left: 0, top: 0,
            width: 'auto', height: 'auto'
		});
		
		var fontSize;
		
		// TODO: This decision of 10 characters is arbitrary. Come up
		// with a smarter decision basis.
		if (tag.text().length < 10) {
			fontSize = resizeLoop(testTag, function(t) {
				return t.width() > width || t.height() > height;
			});
		} else {
			testTag.css('width', width);
			fontSize = resizeLoop(testTag, function(t) {
				return t.height() > height;
			});
		}
		
		testTag.remove();
		tag.css('font-size', fontSize);
		$('#output').append('<div>' + fontSize +'</div>');
	};
	
	$.fn.fitText = function() {
		this.each(function(i, tag) {
			sizeText($(tag));
		});
	};
})(window.jQuery);

(function() {
    $('button').click(function() {
	    $('div.event').fitText();
    });
})();