There are many situations while developing websites when you need to know how long a text string is: not how many characters it has but how long it is in pixels. While this isn't of much importance for regular webdesign it might get useful in certain scenario's like for example when designing Vista Sidebar gadgets.

To provide the experience as originally designed, you want to precisely position all elements within the gadget. While it isn't really difficult in case of static text, properly displaying dynamic content within the limited space on a Sidebar gadget might get quite challenging. Having the possibility to determine the visual length of the text string provides you greater flexibility while designing dynamic Sidebar gadgets.

The most common scenario I have faced was properly displaying a text string within limited space. If the string is visually longer than the available space it has to be visually trimmed. To let the user know that the text was trimmed … (three dots) are appended to the string.

In order to handle the situation described above you will need a few things:

  • a hidden container (further called ruler) which will be used for loading the text. The font of that container must be the same as of the container which will eventually display the text
  • a function for measuring the visual length of a text string
  • a function for visually trimming the text to the desired length in pixels

The Ruler

Creating a ruler is really simple. All you need to do is to put

<span id="ruler"></span>

right under the <body> element and add to your CSS the following definition:

#ruler { visibility: hidden; white-space: nowrap; }

Measuring the visual length of a string

The next step is to create a function which will measure the length of a text in pixels:

String.prototype.visualLength = function()
{
    var ruler = $("ruler");
    ruler.innerHTML = this;
    return ruler.offsetWidth;
}

First of all the function retrieves the reference to the ruler element. For the brevity I have chosen to use a simplified version of the document.getElementById JavaScript function:

function $(id)
{
    return document.getElementById(id);
}

Then the string is being set as the contents of the ruler element. After that the offsetWidth property contains the width in pixels of the ruler element which adjusts itself to fit the text.

While you could create a simple function which would take one parameter I have decided to benefit of the possibility of extending JavaScript classes using the prototype namespace. Having defined the function as above you can now retrieve the length of any string by calling:

var s = "Some text";
var len = s.visualLength();

Visually trimming the text

The last step is to trim the string to the given number of pixels:

String.prototype.trimToPx = function(length)
{
    var tmp = this;
    var trimmed = this;
    if (tmp.visualLength() > length)
    {
        trimmed += "...";
        while (trimmed.visualLength() > length)
        {
            tmp = tmp.substring(0, tmp.length-1);
            trimmed = tmp + "...";
        }
    }
    
    return trimmed;
}

Once again I have chosen to extend the String class so that the trimToPx method can be used on any string. What this function does is, it compares the visual length of a string with the length passed as parameter of the function. If the string is longer, it removes the last char from the string until the string fits in the given length. Additionally, to let the user know that the string has been trimmed, … (three dots) are appended to the string.