Ellipsis or “truncate with dots” via JavaScript

posted in: css, javascript | 0

Internet Explorer comes with a nice CSS feature for truncating text by appending three little dots: text-overflow:ellipsis. Here’s a screen shot:

IE Ellipsis

Unfortunately text-overflow:ellipsis is no standard and not supported by Firefox, Opera, etc. With some JavaScript hacking however you can have something similar to IE ellipsis on all browsers. It even degrades gracefully if JavaScript is disabled.

My solution allows you to simply add a class to an HTML element to make it text-overflow ellipsis. It’s as simple as

<h3 class="ellipsis">The is a heading that gets cut off</h3>

All you have to do in advance is to include ellipsis.js and prototype.js. Jep, I’m using Prototype – but it should be pretty trivial to port it to other JavaScript libraries.

Here’s a demo and here’s the script – MIT-style licensed and tested on IE 6+7, FF 2, Safari 2, Opera 9.

Some Insights

The graceful degradtion is done via a CSS trick. An ellipsis element will have a negative margin of -10000px. It’s like setting its width to some large value, except you get around the Expanding Box bug of Internet Explorer 6. Yeah, I actually decided to not use IEs ellipsis feature, even if I’m on IE – it is pretty nasty to work with (e.g. you have to directly apply a width on ellipsised elements – yuck).

The CSS rule for the ellpisis class is injected into your HTML document via document.write. Here’s the snippet taken from ellipsis.js:

  document.write('<style type="text/css">' +
    '.ellipsis { margin-right:-10000px; }</style>');
  Event.observe(window, "load", function() {
    $$('.ellipsis').each(ellipsis);
  });

The snippet also shows, that once the document is loaded in the browser, the ellipsis function is applied on every element having the ellipsis class. And this function actually contains the JavaScript magic:

function ellipsis(e) {
  var w = e.getWidth() - 10000;
  var t = e.innerHTML;
  e.innerHTML = "<span>" + t + "</span>";
  e = e.down();
  while (t.length > 0 && e.getWidth() >= w) {
    t = t.substr(0, t.length - 1);
    e.innerHTML = t + "...";
  }
}

The function calculates the target width of the element by subtracting the negative margin. Then it will inject a span child containing the original text content of the element. The text in this span will then be truncated until the width of the injected span is smaller than the target width of our element – of course including the three dots 😉 And that’s it…

Drawbacks

  • Since the CSS class for ellipsis is injected via JavaScript, if you want the graceful degredation feature, you have to add the following line manually into your stylesheet:
    .ellipsis { margin-right:-10000px; }
    
  • Never set a right margin on an ellipsis element as my script requires those elements to have a right margin of -10000px, which is set via the inline CSS style.
  • Due to the negative margin, backgrounds, etc. on ellipsis elements will grow to the right – use overflow:hidden on one of the elements containers as a workaround.
  • Resizing ellipsis elements won’t render the dots anew – the layout can not by dynamic.