Click here to Skip to main content
13,630,357 members
Click here to Skip to main content
Add your own
alternative version

Tagged as


30 bookmarked
Posted 8 Sep 2010
Licenced CPOL

Truncating a text string in ASP.NET to fit within a given pixel width

, 8 Sep 2010
Rate this:
Please Sign up or sign in to vote.
How to truncate a text string in ASP.NET to make it fit within a given width specified in pixels.


Sometimes when developing a web application, you have strings that must fit within a certain pixel width (usually the width of a container, like a div, p, td, etc.). This is especially more common with links, as you sometimes need every link to fit within a single line and doesn't wrap to the next line (which will happen if the text of the link is too wide to fit within the width of the container). Or to express it visually, you might have a link that looks like this:


And want to make it look like this:


Client Side vs. Server Side

This can be done either on the client side (using CSS or JavaScript), or on the server side. For a client side solution, the CSS3 text-overflow style (text-overflow: ellipsis OR text-overflow: ellipsis-word) is the simplest and also the standard way, but unfortunately, it's still not fully supported by all browsers. There are some JavaScript solutions that can be used for now until text-overflow is fully supported; still, I prefer a server-side solution as it:

  1. Saves bandwidth (which can also be good for the user experience if the text is too long and takes more time to download, especially if the user has a slow connection).
  2. Is guaranteed to work in all browsers (including the older ones) regardless of whether they have JavaScript enabled, or even support it.

The Code

I wrapped the code required for the truncation into a class, TextTruncator, which you can see here (also included in the download file along with a demo project):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace aspnet_TextTruncator
    public static class TextTruncator
        // Private Properties

        private static Dictionary<string, int[]> _fontWidthDic;
        private static Dictionary<string, int[]> FontWidthDic
                if (_fontWidthDic == null)
                    _fontWidthDic = new Dictionary<string, int[]>();
                return _fontWidthDic;

        // Public Methods

        public static string TruncateText(string text, int textMaxWidth, 
               string fontName, int fontSizeInPixels)
            return TruncateText(text, textMaxWidth, fontName, 
                                fontSizeInPixels, false);

        public static string TruncateText(string text, int textMaxWidth, 
               string fontName, int fontSizeInPixels, bool isFontBold)
            if (string.IsNullOrEmpty(text))
                return text;

            // Check
            if (textMaxWidth < 1 ||
                string.IsNullOrEmpty(fontName) ||
                fontSizeInPixels < 1)
                throw new ArgumentException();

            int[] fontWidthArray = GetFontWidthArray(fontName, 
                                          fontSizeInPixels, isFontBold);
            int ellipsisWidth = fontWidthArray['.'] * 3;
            int totalCharCount = text.Length;
            int textWidth = 0;
            int charIndex = 0;
            for (int i = 0; i < totalCharCount; i++)
                textWidth += fontWidthArray[text[i]];
                if (textWidth > textMaxWidth)
                    return text.Substring(0, charIndex) + "...";
                else if (textWidth + ellipsisWidth <= textMaxWidth)
                    charIndex = i;
            return text;

        // Private Methods

        private static int[] GetFontWidthArray(string fontName, 
                             int fontSizeInPixels, bool isFontBold)
            string fontEntryName = fontName.ToLower() + "_" + 
                   fontSizeInPixels.ToString() + "px" + 
                   (isFontBold ? "_bold" : "");
            int[] fontWidthArray;
            if (!FontWidthDic.TryGetValue(fontEntryName, out fontWidthArray))
                fontWidthArray = CreateFontWidthArray(new Font(fontName, 
                    fontSizeInPixels, isFontBold ? FontStyle.Bold : 
                    FontStyle.Regular, GraphicsUnit.Pixel));
                FontWidthDic[fontEntryName] = fontWidthArray;

            return fontWidthArray;

        private static int[] CreateFontWidthArray(Font font)
            int[] fontWidthArray = new int[256];
            for (int i = 32; i < 256; i++)
                char c = (char)i;
                fontWidthArray[i] = 
                  IsIllegalCharacter(c, false) ? 0 : GetCharWidth(c, font);
            return fontWidthArray;

        private static int GetCharWidth(char c, Font font)
            // Note1: For typography related reasons,
            // TextRenderer.MeasureText() doesn't return the correct
            // width of the character in pixels, hence the need
            // to use this hack (with the '<' & '>'
            // characters and the subtraction). Note that <'
            // and '>' were chosen randomly, other characters 
            // can be used.

            // Note2: As the TextRenderer class is intended
            // to be used with Windows Forms Applications, it has a 
            // special use for the ampersand character (used for Mnemonics).
            // Therefore, we need to check for the 
            // ampersand character and replace it with '&&'
            // to escape it (TextRenderer.MeasureText() will treat 
            // it as one ampersand character)

                TextRenderer.MeasureText("<" + (c == '&' ? "&&" : 
                                         c.ToString()) + ">", font).Width -
                TextRenderer.MeasureText("<>", font).Width;

        private static bool ContainsIllegalCharacters(string text, 
                            bool excludeLineBreaks)
            if (!string.IsNullOrEmpty(text))
                foreach (char c in text)
                    if (IsIllegalCharacter(c, excludeLineBreaks))
                        return true;

            return false;

        private static bool IsIllegalCharacter(char c, bool excludeLineBreaks)
            // See the Windows-1252 encoding
            // (we use ISO-8859-1, but all browsers, or at least
            // IE, FF, Opera, Chrome and Safari,
            // interpret ISO-8859-1 as Windows-1252).
            // For more information,
            // see
            //        IEC_8859-1#ISO-8859-1_and_Windows-1252_confusion

                (c < 32 && (!excludeLineBreaks || c != '\n')) ||
                c > 255 ||
                c == 127 ||
                c == 129 ||
                c == 141 ||
                c == 143 ||
                c == 144 ||
                c == 157;

Using the Code

The class has only one overloaded public method, TruncateText(), which you should call to truncate the text.

Usage Example

In your .aspx page:

<%= TextTruncator.TruncateText("Some text that will " + 
      "likely come from your database, an XML file, or another source", 
      300, "Verdana", 12) %>

Notes About the Code

  • To measure the text width, I use TextRenderer.MeasureText(), which is actually intended for Windows Forms applications, but still can be used with ASP.NET. For performance reasons, I cache the width of the letters so that I don't have to call TextRenderer.MeasureText() again. This was done for good reasons as TextRenderer.MeasureText() can be really slow (in my testing, this change cut the truncation time for a million strings from 8 minutes to 2 seconds!).
  • Because I chose to cache the width of the letters, I had to limit the character set to ISO-8859-1 (for Latin based languages), which works well for my own purposes. If you need this code to work with Unicode, you'll need to remove the letter width caching mechanism and call TextRenderer.MeasureText() every time you want to measure the text width (which will slow things down a bit, but shouldn't be noticeable unless you plan to use this on a very high traffic website and on not-fast-enough machines; you'll have to do your own testing to be sure). You could also change the letter width caching mechanism to use a dictionary instead of an array, and only add the letters to the dictionary when they are actually used.
  • You may notice that in TruncateText(), instead of passing a font object, I pass the font name, size in pixels, and whether it's bold. I do this for convenience reasons, but this should be fairly easy to change if you want to pass a Font object (probably, to also use other font styles like italic, but you'll also need to change the caching mechanism of the letter width).
  • You'll need to add references to the System.Windows.Forms and System.Drawing assemblies in your project in order for this code to work.

A Note About Web Browsers

In many discussions on the web, you'll read that you shouldn't depend on the text width in pixels as there's no guarantee that different browsers will display the text in the same way (i.e., the width of the text may differ from one browser to another). While it's true that there's no guarantee, in my real life testing in all popular browsers (and less popular ones), I found that in all browsers, the width of the text as displayed in the browser never exceeded the maximum width I specified for the text in TruncateText(); sometimes it was slightly smaller (by only a few pixels - that was in the older versions of Safari on Windows), but again, it was never larger. If you are paranoid, like me, always use a 'safety margin'. For example, if the width of the container of the text (div, p, td, or whatever element) is 500px, make the maximum width (that's passed to TruncateText()) less by 10px or 20px, that's 490 or 480.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Waleed Eissa
Software Developer (Senior) Contractor
Australia Australia
Waleed Eissa is a software developer from Cairo, Egypt. He spent 7 years developing software for the banking industry, but has changed focus in recent years to Web development. He specializes in Microsoft technologies, esp. ASP.NET and C#, and is passionate about everything web. His main interests are user experience design (UX), performance tuning and scalability.

He currently lives in Melbourne, Australia.


You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
Zaibot14-Sep-10 2:28
memberZaibot14-Sep-10 2:28 
GeneralRe: My vote of 5 Pin
Waleed Eissa15-Sep-10 20:00
memberWaleed Eissa15-Sep-10 20:00 
GeneralEncoding the & character Pin
RichardJMoss9-Sep-10 4:49
memberRichardJMoss9-Sep-10 4:49 
GeneralRe: Encoding the & character Pin
Waleed Eissa10-Sep-10 0:06
memberWaleed Eissa10-Sep-10 0:06 
GeneralMy vote of 5 Pin
Eric Xue (brokensnow)8-Sep-10 23:33
memberEric Xue (brokensnow)8-Sep-10 23:33 
GeneralRe: My vote of 5 Pin
Waleed Eissa9-Sep-10 23:58
memberWaleed Eissa9-Sep-10 23:58 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web03 | 2.8.180712.1 | Last Updated 8 Sep 2010
Article Copyright 2010 by Waleed Eissa
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid