<html> <head> <!-- By Warren E. Downs, copyright 2016. Based loosely on a single/multiline JQuery using example by Alex, but optimized to avoid JQuery, to use binary search, to use CSS text-overflow: ellipsis for end, and adding marquee option as well. Credit: Marquee: http://jsfiddle.net/jonathansampson/xxuxd/ JQuery version: http://stackoverflow.com/questions/536814/insert-ellipsis-into-html-tag-if-content-too-wide (by Alex, http://stackoverflow.com/users/71953/alex) (Improved with Binary Search as suggested by StanleyH, http://stackoverflow.com/users/475848/stanleyh) --> <meta content="text/html;charset=utf-8" http-equiv="Content-Type"> <meta content="utf-8" http-equiv="encoding"> <style> .single { overflow:hidden; white-space: nowrap; width: 10em; padding: 10px; margin: 0 auto; border: solid 1px blue; } .multiline { overflow: hidden; white-space: wrap; width: 10em; height: 4.5em; padding: 10px; margin: 0 auto; border: solid 1px blue; } .marquee { overflow: hidden; width: 40em; padding: 10px; margin: 0 auto; border: solid 1px blue; } </style> <script> var _marqueeNumber=0; // mode=start,end,middle function clipText(text, len, mode) { if(!mode) { mode="end"; } else { mode=mode.toLowerCase(); } if(mode == "start") { return "…"+clipText(text,len,"_start"); } if(mode == "_start") { return text.substr(text.length - len); } if(mode == "middle") { return clipText(text, len/2, "end") + clipText(text, len/2, "_start"); } return text.substr(0, len) + "…"; } function generateKeyframes(clsName, start, end) { var sec=5; var totalLen=parseFloat(start)-parseFloat(end); if(start.indexOf('em') > -1) { sec=Math.round(totalLen/3); } else if(start.indexOf('px') > -1) { sec=Math.round(totalLen/42); } var style = document.createElement('style'); style.type = 'text/css'; style.innerHTML = 'body {}'; document.getElementsByTagName('head')[0].appendChild(style); this.stylesheet = document.styleSheets[document.styleSheets.length-1]; try { this.stylesheet.insertRule('.'+clsName+' {\n'+ ' animation: '+clsName+' '+sec+'s linear infinite;\n'+ '}\n', this.stylesheet.rules.length); this.stylesheet.insertRule('.'+clsName+':hover {\n'+ ' animation-play-state: paused\n'+ '}\n', this.stylesheet.rules.length); this.stylesheet.insertRule('@keyframes '+clsName+' {\n'+ ' 0% { text-indent: '+start+' }\n'+ ' 100% { text-indent: '+end+' }\n'+ '}', this.stylesheet.rules.length); } catch (e) { console.log(e.message); } } function addClone(el, multiline, estyle) { if(!estyle) { try { estyle=window.getComputedStyle(el); } catch(e) { return null; } } var t = el.cloneNode(true); var s=t.style; //s.display='none'; s.visibility='hidden'; // WARNING: Infinite loop if this is not hidden (e.g. while testing) s.display='inline-block'; s.background='black'; s.color='white'; s.position='absolute'; s.left=0; s.top=0; s.overflow='visible'; s.width=(multiline ? parseFloat(estyle.width) : 'auto'); s.height=(multiline ? 'auto' : parseFloat(estyle.height)); el.parentNode.insertBefore(t, el.nextSibling); return t; } function getTextWidth(el, multiline) { var t=addClone(el, multiline); if(!t) { return null; } var ts=window.getComputedStyle(t); var w=ts.width; if(multiline) { var es=window.getComputedStyle(el); var lines=Math.round(parseInt(ts.height)/parseInt(es.height))*2+0.5; w=w+''; var unit=''; // Extract unit for(var xa=0; xa<w.length; xa++) { var c=w[xa]; if(c <= '0' || c >= '9') { unit=w.substr(xa-1); } } w=parseFloat(w); w*=lines; // Multiply by lines w+=unit; // Append unit again } t.parentNode.removeChild(t); return w; } // cls=class of element to ellipsize // mode=start,end,middle,marq (scrolling marquee instead of clip) function ellipsis(cls, mode) { mode=mode.toLowerCase(); var elems=document.getElementsByClassName(cls); for(xa in elems) { var el=elems[xa]; var multiline = el.className ? el.className.indexOf('multiline') > -1 : true; if(mode == "marq") { var w=getTextWidth(el, multiline); if(!w) { continue; } var mCls="dsmarquee"+(_marqueeNumber++); var es=window.getComputedStyle(el); generateKeyframes(mCls,es.width, '-'+w); el.className+=" "+mCls; continue; } if(mode == "end" && !multiline) { el.style.textOverflow="ellipsis"; continue; } var estyle=null; try { estyle=window.getComputedStyle(el); } catch(e) { continue; } if(estyle.overflow == "hidden") { var text = el.innerHTML; var t=addClone(el, multiline, estyle); function height() { var ts=window.getComputedStyle(t); var es=window.getComputedStyle(el); return parseFloat(ts.height) - parseFloat(es.height); } function width() { var ts=window.getComputedStyle(t); var es=window.getComputedStyle(el); return parseFloat(ts.width) - parseFloat(es.width); } var tooLong = multiline ? height : width; var len=text.length; var diff=1; var olen=0; var jump=len/2; while (len > 0) { var diff=tooLong(); if(diff > 0) { len-=jump; jump/=2; } else if(diff < 0) { len+=jump; } len=Math.round(len); //alert('len='+len+';olen='+olen+';diff='+diff+';jump='+jump+';t='+JSON.stringify(t.innerHTML)); t.innerHTML=clipText(text, len, mode); if(olen == len) { break; } olen=len; } el.innerHTML=t.innerHTML; t.parentNode.removeChild(t); } //break; t.style.visibility='hidden'; } } function testHarness() { ellipsis('ellipsis1', 'start'); ellipsis('ellipsis2', 'end'); ellipsis('ellipsis3', 'middle'); ellipsis('marquee', 'marq') } </script> </head> <body onload="testHarness()"> <div class="single ellipsis1" style="float:left">some long text that should be clipped left</div> <div class="single ellipsis2" style="float:right">right clip long text that should be clipped</div> <div class="single ellipsis3" style="float:center">some long text that should be clipped in the middle</div> <br /> <p class="single marquee">Windows 8 and Windows RT are focused on your life—your friends and family, your apps, and your stuff. With new things like the <a href="http://windows.microsoft.com/en-US/windows-8/start-screen">Start screen</a>, <a href="http://windows.microsoft.com/en-US/windows-8/charms">charms</a>, and a <a href="http://windows.microsoft.com/en-US/windows-8/microsoft-account">Microsoft account</a>, you can spend less time searching and more time doing.</p> <br /> <div class="multiline ellipsis1" style="float:left">Test test test test test test, some more long text, such as asdasdasdasdasd, that should be multiline clipped left(*)</div> <div class="multiline ellipsis2" style="float:right">right clip multiline long text, such as Test test test test test test, and some more long text that should be multiline clipped right.</div> <div class="multiline ellipsis3" style="float:center">Test test test test test test, some more long text, such as asdasdasdasdasd, that should be multiline clipped in the middle(*)</div> <br /> <p class="multiline marquee">Multiline Marquee: Windows 8 and Windows RT are focused on your life—your friends and family, your apps, and your stuff. With new things like the <a href="http://windows.microsoft.com/en-US/windows-8/start-screen">Start screen</a>, <a href="http://windows.microsoft.com/en-US/windows-8/charms">charms</a>, and a <a href="http://windows.microsoft.com/en-US/windows-8/microsoft-account">Microsoft account</a>, you can spend less time searching and more time doing.</p> </body> </html>