Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

css word wrap with ellipsis

Tags:

html

css

Using only CSS, I want both word wrap and then ellipsis once the container is filled vertically. According to research, I can only have ellipsis if white-space: nowrap - which will only give me a single line.

The context is a parent div of known height and variable width, with a child a element that should vertically center itself at all times if it is not at max-height: 100%.

It seems like it should work if display: table in the parent, and display: table-cell and max-height: xxx, text-overflow: ellipsis in the child is specified.

I don't think this is asking a lot, but its late and I may be missing something. Is there a site called still-cant-be-done-in-html5.com?

Fiddle

like image 593
Mark Robbins Avatar asked Apr 28 '15 04:04

Mark Robbins


2 Answers

There is a webkit-only feature called "line clamping" that can achieve what I think you're looking for. Unfortunately, it's non-standard, and there are currently no plans (at least that I'm aware of) to make it part of any standard.

https://css-tricks.com/line-clampin/

It would be accomplished using the following CSS:

.line-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;  
}

With this code, if the element's content fills more than 3 lines with text it will be cut off on the third line with an ellipsis.

There are several different JavaScript libraries that attempt to accomplish similar things, which you can see in the link I've included in this answer. Unfortunately, using standard CSS, text-overflow: ellipsis is limited to just a single line.

Alternatively, there is currently a thread about "region fragments" in the W3C mailing list and how they can be used to make multiline elements have ellipsis, but the spec is still in draft stages and it could be years before it ever makes it into any browsers.

like image 87
Dan Herbert Avatar answered Nov 20 '22 16:11

Dan Herbert


There is now way that I know of that you could do this with pure CSS.

You could use Clamp.js. But I have to warn you, its results are sometimes broken. So I used a little hack that involves setting clamp's line count to 3 and setting the line-height CSS property of the wrapping element to exactly be 1/3rd of the element's height.

// Copying Clamp.min.js here because we cannot execute RAW file from github as it's content type is 'text/plain'.
// Scroll down to see the last line of code.
/*!
 * Clamp.js 0.5.1
 *
 * Copyright 2011-2013, Joseph Schmitt http://joe.sh
 * Released under the WTFPL license
 * http://sam.zoy.org/wtfpl/
 */
(function(){window.$clamp=function(c,d){function s(a,b){n.getComputedStyle||(n.getComputedStyle=function(a,b){this.el=a;this.getPropertyValue=function(b){var c=/(\-([a-z]){1})/g;"float"==b&&(b="styleFloat");c.test(b)&&(b=b.replace(c,function(a,b,c){return c.toUpperCase()}));return a.currentStyle&&a.currentStyle[b]?a.currentStyle[b]:null};return this});return n.getComputedStyle(a,null).getPropertyValue(b)}function t(a){a=a||c.clientHeight;var b=u(c);return Math.max(Math.floor(a/b),0)}function x(a){return u(c)*
a}function u(a){var b=s(a,"line-height");"normal"==b&&(b=1.2*parseInt(s(a,"font-size")));return parseInt(b)}function l(a){if(a.lastChild.children&&0<a.lastChild.children.length)return l(Array.prototype.slice.call(a.children).pop());if(a.lastChild&&a.lastChild.nodeValue&&""!=a.lastChild.nodeValue&&a.lastChild.nodeValue!=b.truncationChar)return a.lastChild;a.lastChild.parentNode.removeChild(a.lastChild);return l(c)}function p(a,d){if(d){var e=a.nodeValue.replace(b.truncationChar,"");f||(h=0<k.length?
k.shift():"",f=e.split(h));1<f.length?(q=f.pop(),r(a,f.join(h))):f=null;m&&(a.nodeValue=a.nodeValue.replace(b.truncationChar,""),c.innerHTML=a.nodeValue+" "+m.innerHTML+b.truncationChar);if(f){if(c.clientHeight<=d)if(0<=k.length&&""!=h)r(a,f.join(h)+h+q),f=null;else return c.innerHTML}else""==h&&(r(a,""),a=l(c),k=b.splitOnChars.slice(0),h=k[0],q=f=null);if(b.animate)setTimeout(function(){p(a,d)},!0===b.animate?10:b.animate);else return p(a,d)}}function r(a,c){a.nodeValue=c+b.truncationChar}d=d||{};
var n=window,b={clamp:d.clamp||2,useNativeClamp:"undefined"!=typeof d.useNativeClamp?d.useNativeClamp:!0,splitOnChars:d.splitOnChars||[".","-","\u2013","\u2014"," "],animate:d.animate||!1,truncationChar:d.truncationChar||"\u2026",truncationHTML:d.truncationHTML},e=c.style,y=c.innerHTML,z="undefined"!=typeof c.style.webkitLineClamp,g=b.clamp,v=g.indexOf&&(-1<g.indexOf("px")||-1<g.indexOf("em")),m;b.truncationHTML&&(m=document.createElement("span"),m.innerHTML=b.truncationHTML);var k=b.splitOnChars.slice(0),
h=k[0],f,q;"auto"==g?g=t():v&&(g=t(parseInt(g)));var w;z&&b.useNativeClamp?(e.overflow="hidden",e.textOverflow="ellipsis",e.webkitBoxOrient="vertical",e.display="-webkit-box",e.webkitLineClamp=g,v&&(e.height=b.clamp+"px")):(e=x(g),e<=c.clientHeight&&(w=p(l(c),e)));return{original:y,clamped:w}}})();


// CODE BEGINS HERE
$clamp(document.getElementById('toclamp'), {
  clamp: 3
});
div {
  width: 100px;
  height: 58px;
  border: 1px solid red;
  line-height: 20px;
}
<div id="toclamp">
  The quick brown fox jumps over the lazy dog.
</div>
<br />
<div id="noclamp">
  The quick brown fox jumps over the lazy dog.
</div>
like image 44
sampathsris Avatar answered Nov 20 '22 14:11

sampathsris