chrisviccaro.com

>> Return to Lab

Multi-line text-trimming in tables > to hell with css3's single-line trim.

A fairly common technique employed when display data in tables is to trim a cell's text content when it is over a certain amount of characters to keep your table rows & columns relatively the same size. CSS3 allows us to do this, but, due to the nature of the way the DOM is rendered, you can only trim a value to be in one-line. To demonstrate:
Activity TypeEvent TitleLocationStart DateEnd DateContactDescription
EventAdvanced Photoshop TechniquesDestin, FL03/14/1203/17/12Nichole V.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis rutrum nisi. Sed sodales tortor vitae velit viverra varius. Cras quis risus mauris, at dapibus eros. Duis feugiat euismod augue vitae sodales. Proin sagittis varius mollis. Phasellus non risus dui, vel adipiscing neque. Pellentesque ut ante mauris. Curabitur id neque eget enim vulputate sagittis. Proin tincidunt fermentum massa, at rutrum lacus suscipit vitae.
EventIntro to HTML5San Diego, CA03/17/1203/17/12Nichole V.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis rutrum nisi. Sed sodales tortor vitae velit viverra varius. Cras quis risus mauris, at dapibus eros. Duis feugiat euismod augue vitae sodales. Proin sagittis varius mollis. Phasellus non risus dui, vel adipiscing neque. Pellentesque ut ante mauris. Curabitur id neque eget enim vulputate sagittis. Proin tincidunt fermentum massa, at rutrum lacus suscipit vitae.

Doing this just takes a few lines of css:

table.sl-text-trim td {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
	    		

But what if you want control over where the trim occurs? This is key to doing a multi-line trim. It just takes a bit of javascript magic. Here's the demo of it in action (resize the browser to see the text-trim vary per window size):

Activity TypeEvent TitleLocationStart DateEnd DateContactDescription
EventAdvanced Photoshop TechniquesDestin, FL03/14/1203/17/12Nichole V.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis rutrum nisi. Sed sodales tortor vitae velit viverra varius. Cras quis risus mauris, at dapibus eros. Duis feugiat euismod augue vitae sodales. Proin sagittis varius mollis. Phasellus non risus dui, vel adipiscing neque. Pellentesque ut ante mauris. Curabitur id neque eget enim vulputate sagittis. Proin tincidunt fermentum massa, at rutrum lacus suscipit vitae.
EventIntro to HTML5San Diego, CA03/17/1203/17/12Nichole V.Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam quis rutrum nisi. Sed sodales tortor vitae velit viverra varius. Cras quis risus mauris, at dapibus eros. Duis feugiat euismod augue vitae sodales. Proin sagittis varius mollis. Phasellus non risus dui, vel adipiscing neque. Pellentesque ut ante mauris. Curabitur id neque eget enim vulputate sagittis. Proin tincidunt fermentum massa, at rutrum lacus suscipit vitae.

The code involves a few preparatory steps:

  • Add the following attribute to your <th> elements like so: <th text-trim="144"> where 144 is the character-limit for that column's cells.
  • Killing the text-trims:
    • Anytime you want to kill the text-trim, add the attribute text-trim-override to the <th> cell like so: <th text-trim-override="true">
    • Anytime you want to re-apply the text-trim, remove the attribute text-trim-override from the <th> cell completely.
  • Define a defaultWindowSize object in JS that has 2 properties, width and height. This will vary per application and is only to set the "strength" of the text-trim. The value you enter in the TH will flex when the window grows or shrinks from the default size. Resize the browser and watch the demo table's text-content:
    var defaultWindowSize = {	width: 1024, height: 768	};
    	    					
  • On a window resize, either with classic JS or with jQuery, iterate through the table-rows, and run the function trimThisRow() passing the <tr> DOMelement as the argument:
    $(window).resize(function() {
    		$("table.ml-text-trim").find('tbody tr').each(function() {
    			trimThisRow(this);
    		});
    });
    	    				
  • Define the trimThisRow function:
    function trimThisRow($tr) {
    	var trimRatio = (window.innerWidth + window.innerHeight) / 
    					(defaultWindowSize.width + defaultWindowSize.height);
    	for (var i = 0, $tc; $tc = $tr.childNodes[i]; i++) {
    		var $th = $($tr).parents('table').find("th:eq("+i+")")[0];
    		var originalText = $tc.attributes["original-text"];
    		var text = originalText ? originalText.value : $tc.firstChild.textContent;
    		if (!originalText) { $tc.setAttribute("original-text",text); }
    		if ($th.attributes["text-trim-override"]) {
    			$tc.firstChild.replaceWholeText(text);
    		}
    		else {
    			var charLimit = $th.attributes["text-trim"] ? 
    					Math.round(trimRatio * $th.attributes["text-trim"].value) : false;
    			if ((charLimit) && (text.length > charLimit)) {			
    				var truncated = text.substr(0,charLimit)+"...";
    				$tc.firstChild.replaceWholeText(truncated);
    			}
    		}
    	}
    	return $tr;
    }		
    	    				
  • Call $(window).resize() onload which will trim the text on page-load.
    $(document).ready(function() { 
    	$(window).resize(); 
    });