Maximum Width Text

Posted by Jared Kipe on | 0 Comments

Tags: , , ,

Ever come across an element where you wished that an automatically wrapping element, like an h1, would automatically change its font-size property to accommodate a certain width? I've got some CSS and Javascript for you.

Why?

Sometimes you have elements on your website that really should have fixed widths, maybe they need to fill a side bar, and you have problems with text that you either can't control or don't want to control too carefully. Maybe it displays content entered by a home user, maybe it was working great until you got a title that was just slightly longer than another title and suddenly you wrapped to a new line.

Finished Examples:

Short Title

Lorem paragraph

Long Title without any Javascript

Lorem paragraph

Long Title with our new Javascript

Lorem paragraph

How?

Here is the HTML for the second and third examples. The structure is the only real important parts. The id="FixedWidthText", is only important for the Javascript, and only for this specific example. (where we don't want all the blocks to have fixed widths)

<div class="block">
	<div class="blockTop">
		<h3 class="blockh3">Long Title without any Javascript</h3>
	</div>
	<p>Lorem paragraph</p>
</div>
 
<div class="block">
	<div class="blockTop">
		<h3 id="FixedWidthText" class="blockh3">Long Title with our new Javascript</h3>
	<p>Lorem paragraph</p>
</div>

CSS

Firstly we need some CSS to define the size of the block. (as well as style them to show off the individual boxes better) The class ".blockTop"  is important for visualizing the part around the h3 that we will be changing the size of implicitly.  ".blockTop" could be an image or maybe have rounded corners.


.block {
	width: 300px;
	background: #eee;
	border: 1px solid #aaa;
	margin-bottom: 20px;
}

.blockTop {
	width: 100%;
	background: #7ab1d8;
}

.block h3.blockh3{
	display: inline-block;
	color: #666;
	font-size: 25px;
	padding-left: 5px;
	line-height: 35px;
	margin: 0;
	*display: inline;
}

Important parts of this CSS:

To be able to fix the width of an element, you need to be able to measure the width of it. This is a problem for the normally block displayed H's (H1, H2 ...) as they have a tendency to be as wide as their surrounding parent element (in this case 300px).

To solve this we change it to display as an inline-block.  Display inline is not good enough, because then the width is only as wide as where the line break is, thus inline would look exactly like the non shrunken example.

The padding-left is only to indent it a little from the left side so that the text isn't right up against the border (like the paragraphs under them), and we didn't use a padding-right because we will be fixing the width anyway so there is no reason to make sure it doesn't touch the right border.

The line-height is somewhat important because I want the text to be centered vertically in the blue part (the containing .blockTop).  (note that the shrunken blue block is the same size and the first example's despite the much larger font)

Javascript

Without any Javascript example block 2 and 3 would look effectively identical.  The key to shrink them is to basically use Javascript to measure the width of the block and if it is beyond a certain width, shrink the "font-size" incrementally until it fits.

jQuery.noConflict();
jQuery(window).load(function() {
	jQuery('#FixedWidthText').textMaxWidth(290, 10);
});

// assumes maxWidth in px, and font-size in px
jQuery.fn.textMaxWidth = function(maxWidth, minFontSize) {
	this.each(function(){
		var width = jQuery(this).width();
		var fontSize = minFontSize + 1;
	
		while (width > maxWidth && fontSize > minFontSize) {
			fontSize = parseInt(jQuery(this).css('font-size'));
			fontSize -= 1;
			jQuery(this).css('font-size', fontSize + 'px');
			width = jQuery(this).width();
		}
	});
}

I'm obviously using the jQuery library to achieve the desired results. I'm also extending jQuery to add the textMaxWidth() method in such a way that it doesn't matter if we called it on jQuery('#FixedWidthText') or jQuery('.blockh3'), the latter would be what we would use if this wasn't a very specific example.

minFontSize is optional, but a pretty good idea. Without it, if you tried to shrink an element that, for some reason, doesn't change its width while the font-size shrinks, you don't end up with an infinite loop.

The most important argument is maxWidth.  This should be smaller than the physical maximum width, in our case 300px, because when the text wraps around to the new line it will effectively be the width of the containing element minus any paddings or margins you assigned.  In our case 300px - 5px padding-left - 5px imaginary padding-right = 290px.

Compatibility?

I've tested this to work as intended in IE8+, Safari, Firefox, Opera, and Chrome.  IE6&7 don't support display: inline-block properly and fail gracefully to the multiple line display: inline.

Download the Source Code:

Max Width Text CSS
Max Width Text Javascript


Post your comment

Comments

No one has commented on this page yet.

RSS feed for comments on this page | RSS feed for all comments