行夹紧(截断多行文本)

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

您希望显示 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