Read more

Flexible overflow handling with CSS and JavaScript

Arne Hartherz
February 07, 2012Software engineer at makandra GmbH

You can use text-overflow to truncate a text using CSS but it does not fit fancy requirements.

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

Here is a hack for the special case where you want to truncate one of two strings in one line that can both vary in length, while fully keeping one of them. See this example screenshot where we never want to show an ellipsis for the distance:

Flexible overflow with optional ellipsis

You can try pretty hard, but there is no cool way with just using floats etc. Margins set in the CSS only work when one of the elements always has a fixed width. This is the result of a journey through that and more, ending up with a jQuery solution.

For it to work, just use the following structure and classes:

<li class="overflow_container">
  <a href="#" class="overflow_truncate">A very long city name</a>
  <span class="overflow_keep">
    (23 miles)
  </span>
</li>

This is the Sass that goes along with it, providing a fallback case for visitors without JavaScript that does regular text-overflow magic:

.overflow_container
  white-space: nowrap
  overflow: hidden
  text-overflow: ellipsis

Here is the code that makes the result pretty, using jQuery:

$(this).find('.overflow_container').each(function() {
  var truncate = $(this).find('.overflow_truncate');
  var keep = $(this).find('.overflow_keep');

  if (truncate && keep) {
    truncate.css('text-overflow', 'ellipsis');
    truncate.css('overflow', 'hidden');

    $.each([ truncate, keep ], function(index, self) {
      $(self).css('float', 'left');
      $(self).css('white-space', 'nowrap');
    });

    keep.html('&nbsp;' + $.trim(keep.html()));

    var keepWidth = keep.outerWidth();
    var containerWidth = $(this).outerWidth();

    truncate.css('max-width', (containerWidth - keepWidth) + 'px');
  }
});

Mind the following:

  • The non-breaking space is prepended to the second element because that one becomes floating. Since that would discard any whitespace between the two elements, we are adding the space (non-breaking to force it appear) that would usually separate them.
  • We're trimming the HTML of the element that should not be truncated so that we don't end up with nsbp + space, causing 2 spaces width.
  • Wrap the code in our unobtrusive JavaScript helper or another way it's run once the DOM is loaded.
Posted by Arne Hartherz to makandra dev (2012-02-07 19:06)