jQuery dynamic text sizing

02/23/2012 -

Sometimes when a variable amount of text needs to be displayed as some sort of a title or a heading in a container with a fixed width and height, one may wish to expand it fully so that it looks consistently big regardless if it’s comprised of a single word, several words or the whole sentence. It's a rather peculiar task and although my web designer colleague might consider this almost a heresy considering certain guidelines, standards and UI consistency, I've recently been working with a client which demanded this kind of functionality. After a brief research, jQuery looked like the most likely candidate in order to produce a reliable cross browser compatible solution. Here's a simple html that I used:

<div class="text-container">
    <strong>My resizable text</strong>
</div>

 
The idea is to expand the font size until it reaches container limits. This must happen out of user's sight in the background and when the ideal font size is found then the text should be displayed. Since the whole thing happens on page load in a glimpse of a second, it doesn't have any visible or noticeable side effects. Here's a sample css:

.text-container
{
    width:600px;
    height: 80px;
    line-height: 80px;
    overflow:hidden;
}
 
.text-container STRONG
{
    position:relative;
    left:-2000px;
    font-family: Arial Black, Arial;
    font-weight:900;
    font-size: 10px;
    white-space: nowrap;
}

 
The text-container element has example fixed width and height, line-height is used as a trick to vertically align the text as described in this article. The relative position and -2000px to the left will place the STRONG element out of visible area, but still active in a sense that its innerWidth and innerHeight properties return values (needed for font size calculation) as opposed to hiding the element with the display:none option. The goal here is to produce the big fat title text, so Arial Black is used by default, font-weight: 900 is used as a fix for the FireFox related Arial Black bug.

The whole dynamic font resizing is just a part of the solution. This will look good if a text is small, only a single word for example. If one wants a larger text to look almost as big, its height needs to be almost the same and this can’t be achieved only with dynamic font size. The trick is to fallback to a more condensed font of the same type, so in my example I used Arial Black, Arial and Arial Narrow. Please note that the first two are standard and should be present on client computers. As for the Arial Narrow, recent Windows versions don’t have it by default, it comes with the Office. So in that case it’s necessary to use embedded fonts technique, like Font Squirrel for example, but that’s out of the scope of this article. Here’s the jQuery that does the dynamic calculation and font family fallback logic:

$(window).load(function () {
    var maxWidth = $('.text-container').first().innerWidth();
    var maxHeight = $('.text-container').first().innerHeight();
    var elem = $('.text-container STRONG');
    var fontSize = parseInt(elem.css('font-size'));
    while (elem.innerWidth() < maxWidth && elem.innerHeight() < maxHeight) {
        fontSize++;
        elem.css('font-size', fontSize + 'px');
    }
    //if there's still space to grow in height, fallback to Arial
    if (elem.innerHeight() < maxHeight) {
        elem.css('font-family', 'Arial');
        elem.css('font-weight', 'bold');
        while (elem.innerWidth() < maxWidth && elem.innerHeight() < maxHeight) {
            fontSize++;
            elem.css('font-size', fontSize + 'px');
        }
    }
    //if there's still space to grow in height, fallback to Arial Narrow ('ArialNarrow' is used as embedded font in case a client doesn't have the 'Arial Narrow' installed)
    if (elem.innerHeight() < maxHeight) {
        elem.css('font-family', "'Arial Narrow', 'ArialNarrow', Arial");
        elem.css('font-stretch', 'ultra-condensed'); //Firefox doesn't recognize Arial Narrow, it requires Arial with font-stretch: ultra-condensed in order to render Arial Narrow
        while (elem.innerWidth() < maxWidth && elem.innerHeight() < maxHeight) {
            fontSize++;
            elem.css('font-size', fontSize + 'px');
        }
    }
    fontSize--;
    elem.css('font-size', fontSize + 'px');
    elem.css("left", "0px");
});

 Of course, no solution will work if the text is too large, but one might say that within reasonable text length this solution is good enough.
Rated 5.00, 3 vote(s).