您希望显示 X 行文本。任何超出此行数的内容:优雅地截断。这就是“行夹紧”,这是一个完全合法的需求。当您可以确定文本的特定行数时,就可以根据包含该文本的元素创建更强大、更可靠的网格,并实现一些对称的美学和谐。
有几种方法可以实现,但没有一种方法特别出色。
如果上述解释不够清晰,请想象您有一些类似如下的 HTML 代码
<div class="module">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</div>
并且您希望将其限制在一个容器中正好三行。如下所示:
在所有这些示例中,让我们假设我们有一个“模块”。
.module {
width: 250px;
overflow: hidden;
}
标准化方法
我过去称之为“奇怪的 WebKit flexbox 方法”,但更奇怪的是,规范现在将其包含在溢出模块中,包括旧的 flexbox。而且,Firefox 正是这样实现的。随着 Edge 成为 Chromium,这种奇怪的技术变得更有用,而不是更少用。
.line-clamp {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
尽管语法很奇怪,但这非常棒,也正是我们需要的。这是一个用于尝试它的游乐场
公平地说,它确实很奇怪。为什么它需要是 flexbox 东西(那个旧版本)?没有它就无法工作。而且它非常脆弱。假设您希望模块(或段落)具有一些填充。您不能这样做,因为填充会暴露额外的行。这就是我们从最初非标准化属性的半成品中得到的结果。
淡出方法
此技术的核心只是以可预测的方式设置模块的高度。假设您将line-height
设置为1.2em
。如果我们希望显示三行文本,我们可以将容器的高度设置为3.6em
(1.2em × 3)。隐藏的溢出将隐藏其余部分。
但是,这样简单地截断文本可能有点笨拙。理想情况下,我们会添加省略号,但我们无法可靠地定位它们。因此,我们将使文本淡出,以实现相同类型的传达(“还有更多...”)。
要使最后一行淡出,我们创建一个框(伪元素非常适合),并在其顶部覆盖一个从透明到背景颜色的渐变。使其宽度几乎与容器一样宽是最好的,以防最后一行很短。因为我们知道line-height
,所以我们可以使伪元素框的高度正好为一行。
.fade {
position: relative;
height: 3.6em; /* exactly three lines */
}
.fade::after {
content: "";
text-align: right;
position: absolute;
bottom: 0;
right: 0;
width: 70%;
height: 1.2em;
background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 50%);
}
Opera 溢出方法
Opera 作为其自己的渲染引擎,早已停止使用。仅出于历史原因保留此内容。
与 WebKit 一样,Opera 也有自己的处理方法。它们会在您希望的行上应用省略号。当然,Presto(Opera 在 Blink 之前的渲染引擎)的时钟正在滴答作响,因此这并没有什么特别的用处。也许它仍然可以为未来的实施提供信息。
.last-line {
height: 3.6em; /* exactly three lines */
text-overflow: -o-ellipsis-lastline;
}
Clamp.js 方法
有志者事竟成(使用 JavaScript)。我认为这是一句谚语。Joseph J. Schmitt 有一个出色的无库 JavaScript 东西,称为Clamp.js,用于以跨浏览器的方式实现这一点。
var module = document.getElementById("clamp-this-module");
$clamp(module, {clamp: 3});
确保您直接在其内部定位包含文本的元素。最初我尝试将 ID 放置在模块上,这在 Chrome/Safari 中有效,但在 Firefox 中失败了。将其放在<p>
上使其在两者中都能工作(感谢Merri)。
隐藏溢出并放置省略号的纯 CSS 方法
诀窍是将max-height
设置为最大行数乘以line-height
。
html {
--lh: 1.4rem;
line-height: var(--lh);
}
.truncate-overflow {
--max-lines: 3;
position: relative;
max-height: calc(var(--lh) * var(--max-lines));
overflow: hidden;
padding-right: 1rem; /* space for ellipsis */
}
.truncate-overflow::before {
position: absolute;
content: "...";
inset-block-end: 0; /* "bottom" */
inset-inline-end: 0; /* "right" */
}
.truncate-overflow::after {
content: "";
position: absolute;
inset-inline-end: 0; /* "right" */
width: 1rem;
height: 1rem;
background: white;
}
其余部分是在行尾放置“...”省略号,但仅当文本超过最大行数时才放置。
演示
更新:更多好方法!
- 有一种非常巧妙的纯 CSS 方法可以实现这一点,发布在 Mobify 博客上更新:已删除链接,博客已失效,此处添加了技术。
- Vesa Piittinen 创建了Clamp.js 的替代方法。
“与 Clamp.js 不同,它保留了夹紧元素中的所有文本,并使用text-overflow
来实现神奇效果。” - FT Labs 也有创建了一个 JavaScript 插件来完成这项工作。它很不错,因为您不必指定行数,它在文本溢出容器时就会发生,因此设计决策保留在 CSS 中。
- Succinct:“一个用于截断多行文本的小型 jQuery 插件。”
这些示例已添加到主 Pen中。
还有 DollarShaveClub 的Shave
Clamp.js 方法实际上对我不起作用(FF 20)。我仍然认为我更喜欢渐变叠加方法。然后可以在伪元素上放置另一个元素以进一步指示更多内容(“阅读更多”链接)。也就是说,如果没有对 IE 进行一些重大修改,这仍然让我们在寻找一种良好的跨浏览器方法。
Matt,我在 FF 20.0 on Mac 上也看到了同样的情况。
以下是感兴趣人士的屏幕截图:http://i.imgur.com/WJGNQmD.png
好的,看起来这是一个已知问题:https://github.com/josephschmitt/Clamp.js/issues/3
如果使用 FF20,您可以在此处查看其运行情况:http://codepen.io/jcummins/pen/nvEmf
以下是更新后的屏幕截图:http://i.imgur.com/Ubv3NLl.png
Selectivizr?
自从开始从事 Web 开发工作以来,尝试实现优雅的截断一直是我存在的祸根。感谢您指出此功能;我一定会使用它。
我实现了一个简单的 jQuery 插件,它允许您实现类似的功能,甚至更多。
没有对 text-overflow: ellipsis 的爱?
它仅在激活了 white-space: nowrap 时才有效。
text-overflow: ellipsis 仅适用于第一行也是唯一的一行文本。
本文的重点是,当文本换行到多行时,我们可以使用什么来指示溢出。
您实际上可以使用
white-space: pre
,它对每一行都有效。这意味着您可以编写一些 JavaScript 来添加大约两行更改,然后最后一行会显示省略号。
困难的部分在于以高效的方式测量文本。
我不知道pre与overflow的交叉,Merri,谢谢你的信息。
尽管如此,该解决方案仍需要JavaScript,并且会更改内容本身。
您复制粘贴的文本中将包含换行符。
这对于我通常的用例来说是不可接受的,但其他人可能不会介意。
W3C在其“CSS Overflow模块级别3”工作草案中针对此问题。
基于这个非常早期的规范,理论上我们可以像这样进行3行截断
.line-clamp {
overflow: fragments;
}
.line-clamp::nth-fragment(1){
max-lines: 3;
}
.line-clamp::nth-fragment(2){
display:none;
}
诚然,这是一个早期的规范,但这实际上没有任何帮助。我们已经能够在n行后截断文本,我们的问题是在所需行的末尾添加省略号。
所以我们有了片段,除了第一个之外,我们隐藏了所有片段。但是我们如何处理第一个片段呢?
在我看来,该规范更多的是解决CSS区域的相同问题。但我们真正需要的是一些:overflowing伪类。设计师们从1998年开始就一直在要求它……
淡出方式有一个小问题……如果文本恰好适合3行呢?在这种情况下,您不希望淡出第三行的末尾,因为没有更多内容跟随。当然,如果您知道文本适合,您就不会尝试截断它,但如果您不知道……
我也喜欢渐变方式(当然是在一个体面的标准化截断方法之后)。我真的认为您需要在伪元素上使用
pointer-events: none;
。看起来Clamp.js不起作用。因此,经过一些反复试验,这似乎可以可靠地跨浏览器工作
http://codepen.io/Merri/pen/Dsuim
它需要一些进一步的优化,它真的不需要像它那样编辑数据字符串,它可以直接在第一个替换回调循环中创建元素。
淡出技术类似于polygon Polygon 使用的技术。
感谢您提供有用的帖子,Chris。
FT Labs 的开发人员还开发了ftellipsis,它执行相同的操作,并在非 Webkit 浏览器中回退到截断文本并在溢出行的末尾定位元素。
测试过了。与 Clamp.js 一样,它似乎只在 Webkit 浏览器中有效。
已将其添加到演示中,谢谢!
……并且使用了错误的名称……无论如何。Clamp.js 最终有效,Chris 只是在他的示例中目标元素错误(id 应该在段落中而不是在 div 中)。
我不喜欢 Clamp.js 的一点是它如何从元素中删除原始文本。
另一种仅使用 CSS 的方法之前在此博客上链接过,可以在这里找到:http://www.mobify.com/blog/multiline-ellipsis-in-pure-css/
作为网页设计的新手,我发现所有这些小事情都令人抓狂。甚至编程游戏也没有网页设计那么头疼,我感到惊讶。
几天前我不得不为我的网站做完全相同的事情,我找到的解决方案是使用 PHP 进行文字换行并计算行数。更不用说获取一个脚本来确保不将 HTML 标签算作单词了。
那么你们中的哪一位打算编写一种全新的网站制作方法,一种在浏览器之间逻辑一致且无需痛苦即可完成基本操作的方法呢?当你做到这一点时,我会向你的 PayPal 发送 100 美元,甚至可能更多。
哇!我喜欢 Clamp.js,它似乎只在 -webkit- 浏览器中有效。
一些关于如何实现此目的的有趣示例,当我们过去这样做时,我们使用 PHP 来完成此操作,如果幸运的话,我们很快就可以摆脱它!
我不明白“淡出方式”到底是如何工作的,因为您无法保证跨浏览器相同的字体大小。
即使您设置了行高和字体大小,文本仍然会在不同的区域溢出。根据浏览器,它可能会在容器结束之前停止,但在其他浏览器上,最后一行可能会被容器截断一半。
我最近在网上搜索了这个问题的解决方案,我找到了一个名为dotdotdot的 jQuery 插件。显然,这不是纯 CSS 解决方案,但 CSS 有效地控制了它的应用,因为库会测量文本容器,并且仅应用于溢出的内容。
“dotdotdot”最酷的功能之一(也是我选择它而不是其他解决方案的主要原因)是能够确保特定内容保持可见,或者在需要省略号时添加自定义内容。在我的特定情况下,我正在电子商务网站上剪辑产品描述,并且需要确保产品 ID 在描述的末尾可见,即使存在省略号。
到目前为止,该库一直为我提供了很好的服务,我强烈推荐它。我还没有需要“无依赖”版本(没有 jQuery),但当我需要时,我可能会联系开发人员要求一个原生 JS 端口,或者自己动手。
查看https://gist.github.com/depoulo/5832073
仅 CSS,考虑了文本长度与您要显示的行数相同的情况(在这种情况下您不需要点),并且您可以轻松地将 -webkit-line-clamp 切换实现到其中。
Opera 溢出方式不起作用。我猜是因为 Opera 正在更改其自身的引擎。
我喜欢 Clamp.js,它似乎只在 -webkit- 浏览器中有效。