Tuesday, December 18, 2012

Elegant truncated text with ellipses in web

Sometimes text is big than allowed space. Assume you have a table column with a very long text and don't want to have line breaks or make the table bigger in order to show the text completely. Having a fluid truncated (clipped) text with three dots at the end would be a good option. It would be nice to show a truncated text with ... and put a tooltip which displays the whole text on mouseover. Furthemore, the text should display more content or less content dynamically when resizing browser and the available space gets bigger or shrunk. How to deal with fluid truncated text? Well, there are some JavaScript solutions with advanced configuration. One of them is e.g. dotdotdot and the another one is trunk8

But in simple cases we don't need JavaScript at all. There is a CSS property text-overflow: ellipsis which works fine on container elements (like div) with white-space: nowrap and overflow: hidden. I defined a style class truncate which can be applied to any container element.
.truncate {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
    -ms-text-overflow: ellipsis;
    display: block;
    position: absolute;
}
This works smoothly. Example:
<div class="truncate">
    My very very very very very very very very very long text
</div>
The text will fit the space of the div element now.

As I develop JSF applications I need it for text in PrimeFaces p:column (rendered as td element). For that we need to set a max. width on p:column. For my project I decided to restrict the max. width to 160px. Style classes applied to p:column and the inner div (containing the text) look as follows:
.truncate {
    max-width: 160px;
    width: 160 px\9;
}

.truncate > div {
    width: 160 px\9;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
    -ms-text-overflow: ellipsis;
    display: block;
    position: absolute;
}
\9 is a hack for IE7 / IE8. Unfortunately, I could not do text in table's columns fluid for IE7 / E8, so that I set a fix width 160px. The code in XHTML is like this one:
<p:column headerText="Description" sortBy="#{user.description}" styleClass="truncate">
    <h:outputText id="desc" value="#{user.description}"/>
    <pe:tooltip for="desc" value="#{user.description}"/>
</p:column>
And a final picture to complete this blog post.


The visible text's content (in the column "Description") is adjusted automatically while the table changes its size. There are no line breaks in columns when some text doesn't fit the available column's space. The table looks compacted.

7 comments:

  1. ATM you output the content of your table cell twice... would'nt it be easiert to let the content of the cell be truncated using elipsis, but use the full content for the overlay?

    ReplyDelete
  2. I'm not sure I have understood you. The content of a cell is a full text (in generated HTML), but it is shown truncated for users. Tooltip contains the same full text again to show not truncated text on mouseover.

    ReplyDelete
  3. Thanks Oleg!!! I was looking for this!!!! Great!!!

    ReplyDelete
  4. Hello Oleg. Is it possible to bind tooltip to the POJO to display some advanced information (not only text) in the tooltip?

    Is it possible to create tooltip for every element in DataTable / SelectOneMenu?

    Thanks.

    ReplyDelete
  5. Sure, POJO and tooltips for every element in DataTable are possible. Showcase is here http://fractalsoft.net/primeext-showcase-mojarra/views/tooltip.jsf

    Not sure about SelectOneMenu. Never tried it. You can try with jQuery selector in "forSelector" for option elements in SelectOneMenu.

    ReplyDelete
  6. Hi Oleg, I used this tip for Primefaces 4.0 and I had to change some things.

    I replaced css "div" class for "span" and "position:absolute" for "position:relative". I also removed "width" attribute because I want autoresizing of columns with max-width. Here is an example:

    .truncate-column {
    max-width: 120px;
    }

    .truncate-column > span {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
    -ms-text-overflow: ellipsis;
    display: block;
    position: relative;
    }

    ReplyDelete
  7. tried both the approaches with primefaces 4.0. There are no span or div components under column. So pt everything under . truncate {} and removed display:block as it was blocking the extended view. Thanks for the tips.

    ReplyDelete

Note: Only a member of this blog may post a comment.