views:

6736

answers:

6

Is there any good way of truncating text with plain HTML and CSS, so that dynamic content can fit in a fixed-width-and-height layout?

I've been truncating server-side by logical width (i.e. a blindly-guessed number of characters), but since a 'w' is wider than an 'i' this tends to be suboptimal, and also requires me to re-guess (and keep tweaking) the number of characters for every fixed width. Ideally the truncation would happen in the browser, which knows the physical width of the rendered text.

I've found that IE has a text-overflow: ellipsis property that does exactly what I want, but I need this to be cross-browser. This property seems to be (somewhat?) standard but isn't supported by Firefox. I've found various workarounds based on overflow: hidden, but they either don't display an ellipsis (I want the user to know the content was truncated), or display it all the time (even if the content wasn't truncated).

Does anyone have a good way of fitting dynamic text in a fixed layout, or is server-side truncation by logical width as good as I'm going to get for now?

+12  A: 

If you're OK with a JavaScript solution, there's a jQuery plug-in to do this in a cross-browser fashion - see http://devongovett.wordpress.com/2009/04/06/text-overflow-ellipsis-for-firefox-via-jquery/

RichieHindle
That's definitely useful, thanks!Seems like all the browsers except Firefox support the CSS property, so with this plugin, the only people it wouldn't work for are Firefox users who've disabled Javascript - and it's a graceful degradation anyway.Any idea what the performance implications are like?
Sam Stokes
No, sorry... I haven't used the code in real life, just played with the demo. It would be easy to take the demo and cut-and-paste it a hundred times into the same page.
RichieHindle
JavaScript truncate() (be it dot-string for jQuery or Prototype or whatever) are only a half-way solution, because they do not take into account the character width. So, if you want to truncate text because of a pre-defined limited space, those functions only work reliably when using monospaced fonts.Any serious solution would have to operate on glyphs, not on character count.
Matthias
@Matthias: Perhaps the code has been updated since you tested it, but I've just looked at the demo and it works perfectly with a variable-width font.
RichieHindle
A: 

Yeah, this has been a major pain for years.

Impossible to get 100% on server side diff browsers, user style sheets and the cntrl +/- keys.

But if its a REAL bummer of not having this, you could just generate an img through an ashx on the server with your font & size.

I have done it. No shame in it haha

Chad Grant
+28  A: 

Justin Maxwell has cross browser CSS solution. It does come with the downside however of not allowing the text to be selected in Firefox. Check out his guest post on Matt Snider's blog for the full details on how this works.

Update: this technique also prevents updating the content of the node in JavaScript using the innerHTML property in Firefox. See the end of this post for a workaround.

CSS

.ellipsis {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
    -moz-binding: url('assets/xml/ellipsis.xml#ellipsis');
}

ellipsis.xml file contents

<?xml version="1.0"?>
<bindings
  xmlns="http://www.mozilla.org/xbl"
  xmlns:xbl="http://www.mozilla.org/xbl"
  xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
>
    <binding id="ellipsis">
        <content>
            <xul:window>
                <xul:description crop="end" xbl:inherits="value=xbl:text"><children/></xul:description>
            </xul:window>
        </content>
    </binding>
</bindings>

Updating node content

To update the content of a node in a way that works in Firefox use the following:

var replaceEllipsis(node, content) {
    node.innerHTML = content;
    // use your favorite framework to detect the gecko browser
    if (YAHOO.env.ua.gecko) {
        var pnode = node.parentNode,
            newNode = node.cloneNode(true);

        pnode.replaceChild(newNode, node);
    }
};

See Matt Snider's post for an explanation of how this works.

Simon Lieschke
That's awesome, thanks for pointing it out!The unselectable text and restrictions on what content can go in the truncated div are a shame, but generally that looks like a good solution.
Sam Stokes
Only real frustration I've hit is that spaces are rendered as  , so indentation isn't really feasible... =/
Matchu
I ran across this same problem too. I can't believe Firefox doesn't support this in some form yet.
mcjabberz
does this approach work for anyone on OPTION elements of SELECT controls on Webkit and IE8. Webkit doesnt seem to be doing anything for me and IE8 just clips it without the ellipsis.
Rajat
Microsoft's documentation for `text-overflow` doesn't indicate support for `option` elements (see the **Applies To** section at http://msdn.microsoft.com/en-us/library/ms531174(VS.85).aspx).
Simon Lieschke
Just a heads up that the XUL hack currently doesn't work in Firefox 4.0 (which is in development as of writing). I'll keep people updated. https://bugzilla.mozilla.org/show_bug.cgi?id=312156#c94
Simon Lieschke
+1  A: 

For reference, here's a link to the "bug" tracking text-overflow: ellipsis support in Firefox. Sounds like Firefox is the only major browser left that doesn't support a native CSS solution.

Sam Stokes
A: 

I have a table which displays long links in anchor tags in the table cells. I have to truncate the links to a certain width and display ellipsis. I have used Justin Maxwell's solution and it works!

But my team mate insists on doing the truncation in code on the server side. For the ellipsis to show, I think doing it in css is a better solution.

Purni
The anchor tags stopped displaying the ellipsis in IE 8. Matt Snider helped by suggesting that I add style="display: block" to the anchor tag. Ellipsis now shows in FF3.5 and IE8.
Purni
+1  A: 

Another solution to the problem could be the following set of CSS rules:

.ellipsis{
 white-space:nowrap;
 overflow:hidden;
}

.ellipsis:after{
  content:'...';
}

The only drawback with the above CSS is that it would add the "..." irrespective of whether the text-overflows the container or not. Still, if you have a case where you have a bunch of elements and are sure that content will overflow, this one would be a simpler set of rules.

My two cents. Hats off to the original technique by Justin Maxwell

Rajat