如何仅显示 div 的前几行(clamp)?

11
我有一系列的
,其中我显示了更长文档的预览。这些文档使用不同的字体样式,所以我没有一个恒定的行高。这是一个例子:http://jsfiddle.net/z56vn/ 我只需要显示每个文档的前几行。我们已经确定300px左右是适当的。如果我简单地将
的最大高度设置为300px,那么根据文本属性(大小、填充、边距),最后一行的底部就会被剪切。
如何为每个块设置接近300px的最大高度,但不会导致剪切?
解决方案可以使用CSS、Javascript和jQuery。

这两个问题类似,但它们的解决方案都假设行高是恒定的。


1
你需要考虑所有因素:字体大小、行高、字符宽度、容器宽度/高度等,然后计算出最大的字符数,以确保其适合容器。 - David Hellsing
使用CSS如何处理多行溢出的块? - Adriano
5个回答

19
使用JavaScript完美计算所有因数的算法过于复杂。
使用CSS3有line-clamp功能。
但是这仅适用于现代浏览器。
p{
 margin:20px;
 overflow: hidden;
 text-overflow: ellipsis;
 display: -webkit-box;
 -webkit-line-clamp: 3;
 -webkit-box-orient: vertical;
}

演示

http://jsfiddle.net/MM29r/

这让您可以设置在添加3个点之前要显示的行数。
现在您想要300像素... 所以:
var p=document.getElementsByTagName('p')[0],
lineheight=parseInt(window.getComputedStyle(p).getPropertyValue("line-height"));
var lines=Math.floor(300/lineheight);
p.style['-webkit-line-clamp']=lines;

所以这将给你一个不超过300像素的元素。 演示

http://jsfiddle.net/MM29r/1/

http://jsfiddle.net/MM29r/2/

需要的值:line-height 现在,如果您想使框的高度恰好为300px,请添加段落的边距或填充。但这取决于您的喜好。
如果您有任何问题,请询问。
注意
每个js函数都会通过计算单词末尾添加3个点,这对于应用于真实世界的网站来说是资源密集型的。
更好的方法是一次计算每个段落,并将夹紧的结果添加到db中或将其存储在静态网站中。
但是,每个浏览器以不同的方式显示字体。
编辑
以下是显示部分内容的不同方法。使用max-height和-webkit-column-count

https://stackoverflow.com/a/20691677/2450730

演示

http://jsfiddle.net/HNF3d/10/

支持程度略高于line-clamp,并且能够显示全部内容。 编辑2 在底部逐渐消失的图片。
p{
 width:300px;
 max-height:300px;
 overflow:hidden;
}
p:before{
 content:"";
 display:block;
 position:absolute;
 margin-top:240px;
 background:-webkit-linear-gradient(top,rgba(255,255,255,0) 0%,rgba(255,255,255,1) 80%);
 height:60px;
 width:300px;
}

http://jsfiddle.net/MM29r/9/

编辑3

在旧版浏览器中实现图片渐隐效果(使用真实图片链接,而非base64编码)

http://jsfiddle.net/MM29r/13/


在低CPU设备上计算每个div需要1秒或更长时间。而且,由于每个浏览器以不同的方式显示字体,因此该函数基本上是不可能的。 - cocco
但是想象一下,如果文档中有一个 p 元素,它的 display 属性设置为 inline。我不能简单地遍历每个已知的块级元素并计算它们的行高。对于每个元素,我都必须检查它是否隐藏、折叠、内联、浮动或使用与默认值不同的定位。 - Sylvain
是的,这很混乱。你试图做一些几乎不可能的事情。使用max-height,在底部添加一个渐变图片。忘记那三个点。我给你写了一个例子。 - cocco
在新的一行中,3个点... 哎呀.. 大小不同,它们并不完全是300像素或更少。 - cocco
1
为旧版浏览器添加了淡入淡出的图像。 - cocco
显示剩余10条评论

3
一种替代方法是使用jQuery插件dotdotdot
它的用法如下:
$("div.text_element").dotdotdot({
  ellipsis : "...",
  wrap : "word"
});

这样,您只需关注div尺寸而不是行高或其他CSS属性。此外,它允许您触发事件来显示和隐藏隐藏的文本。


dotdotdot 是唯一在所有浏览器中都适用于我(固定高度容器内有一个长链接)的解决方案。 - parrker9

1
你可以使用由Joseph Schmitt创建的JavaScript插件Clamp.js。代码的minified版本可以在这里找到。 然后,你可以像这样使用它:
var elem = document.getElementsByTagName("div");

for(var z=0;z < elem.length; z++){
  $clams(elem[z], {clamp: '300px'});
}

或者,如果不是所有的 <div> 都需要夹紧,您可以使用 getElementsByClassName


1
你应该寻找行截断技术。这里可以找到它们的列表 http://css-tricks.com/line-clampin/。正如你所看到的,上面的链接解释了各种实现行截断的方法,但只有其中一种是真正的跨浏览器解决方案。似乎有一个JavaScript库可以完美解决这个问题,即使使用不同的字体大小或样式也能工作。 Clamp.js [ https://github.com/josephschmitt/Clamp.js ]。这是一个例子。
var paragraph = document.getElementById("myParagraphId");

$clamp(paragraph, {clamp: 3});

1
+1...但你真的应该在链接中包含技术摘要。这将保护你的链接不会失效,同时允许S.O.用户在不离开网站的情况下找到答案...这也许就是为什么当我写这个评论时,有人给你点了踩。 - Zach Lysobey
如果链接失效,你的帖子就毫无用处。 - Felix Kling
他给问题命名的简单事实是有帮助的(夹紧)。 - Sylvain

0

在这种情况下,我会这样做:

首先,我们需要获取div并找出行高,所以我假设您已经将div作为jQuery对象获取到了。

var $divToClamp = $("#");
var $cloneDiv = $divToClamp.clone();
$divToClamp.insertAfter($cloneDiv.html("A"));
// created a new div as same place with the div to get same css, from parents, class etc.
// i don t know how jQuery handles the ids you must check that
var lineHeightToClamp = $cloneDiv.height() * 3;
$cloneDiv.remove();
// remove the clone we are done with it this does not work create clone div as fixed position back of the actual div and visibility hidden (not display:none)
//now we now the line-height for 3 lines set the css
$divToClamp.css({
      overflow : "hidden",
      lineHeight: lineHeightToClamp
    });

类似这样的代码应该可以解决你的问题,但是可能会有一些例外,比如 div 的 margin 我不确定 $cloneDiv.height() 是否包括它们。

另外,如果你的 div 中还有其他元素(比如 span),并且它们具有不同的 CSS 样式,那么情况也会发生变化。

希望这能帮到你。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接