返回首页

如何实现单行/多行文本溢出的省略样式?

问题解析

文本溢出处理是 UI 开发中的常见需求,涉及到文本截断、省略号显示等。面试考察这个问题,主要是想了解候选人对 CSS 文本属性的掌握,以及是否能处理多行截断的复杂场景。

单行文本溢出省略

实现代码

.single-line {
  /* 核心三属性 */
  white-space: nowrap;      /* 1. 禁止换行 */
  overflow: hidden;         /* 2. 溢出隐藏 */
  text-overflow: ellipsis;  /* 3. 显示省略号 */

  /* 需要设置宽度 */
  width: 200px;
}

原理说明

属性 作用
white-space: nowrap 强制文本在一行显示,不换行
overflow: hidden 隐藏超出容器的内容
text-overflow: ellipsis 用省略号表示被截断的文本

注意text-overflow 只有在设置了 overflow: hiddenwhite-space: nowrap 时才生效。

可选值

text-overflow: clip;      /* 直接裁切(默认) */
text-overflow: ellipsis;  /* 显示省略号 */
text-overflow: "自定义";   /* 自定义字符串(部分浏览器支持) */

多行文本溢出省略

方案一:WebKit 私有属性(推荐)

.multi-line {
  display: -webkit-box;           /* 弹性盒模型 */
  -webkit-box-orient: vertical;   /* 垂直排列 */
  -webkit-line-clamp: 3;          /* 限制 3 行 */
  overflow: hidden;
}

优点

  • 代码简洁
  • 省略号位置准确

缺点

  • WebKit 私有属性(-webkit- 前缀)
  • 兼容性:主流浏览器都支持,IE 不支持

方案二:伪元素 + 渐变遮罩

.line-clamp {
  position: relative;
  line-height: 1.5;
  max-height: 4.5em;  /* 行高 × 行数 */
  overflow: hidden;
}

.line-clamp::after {
  content: "...";
  position: absolute;
  bottom: 0;
  right: 0;
  padding-left: 20px;
  background: linear-gradient(to right, transparent, white 50%);
}

优点

  • 兼容性好
  • 可控性强

缺点

  • 省略号位置可能不准确
  • 需要背景色配合遮罩

方案三:纯 CSS 定位(旧方案)

.clamp-old {
  position: relative;
  line-height: 20px;
  height: 60px;  /* 行高 × 3行 */
  overflow: hidden;
}

.clamp-old::after {
  content: "...";
  position: absolute;
  bottom: 0;
  right: 0;
  background: white;
  padding: 0 5px;
}

深入理解

-webkit-line-clamp 详解

.line-clamp {
  /* 必需 */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;

  /* 可选增强 */
  text-overflow: ellipsis;
}

注意事项

  • 需要配合 overflow: hidden 使用
  • 只在 WebKit/Blink 内核浏览器生效(Chrome, Safari, Edge, Opera)
  • Firefox 从 68 版本开始支持

兼容性更好的方案

/* 使用 CSS 变量提高可维护性 */
.line-clamp {
  --line-height: 1.5;
  --lines: 3;

  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: var(--lines);
  line-height: var(--line-height);
  max-height: calc(var(--line-height) * var(--lines) * 1em);
  overflow: hidden;
}

JavaScript 辅助方案

当 CSS 方案无法满足需求时(如需要动态计算行数):

function clampText(element, maxLines) {
  const lineHeight = parseInt(getComputedStyle(element).lineHeight);
  const maxHeight = lineHeight * maxLines;

  if (element.scrollHeight > maxHeight) {
    // 二分法查找截断位置
    let text = element.textContent;
    let start = 0;
    let end = text.length;

    while (start < end) {
      const mid = Math.floor((start + end) / 2);
      element.textContent = text.slice(0, mid) + '...';

      if (element.scrollHeight > maxHeight) {
        end = mid - 1;
      } else {
        start = mid + 1;
      }
    }
  }
}

英文长单词处理

.text-wrap {
  /* 允许在单词内换行 */
  word-break: break-all;

  /* 或 */
  overflow-wrap: break-word;
  word-wrap: break-word; /* 旧属性 */

  /* 连字符换行 */
  hyphens: auto;
}

最佳实践

可复用的工具类

/* 单行省略 */
.text-ellipsis {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 多行省略 */
.line-clamp-2 {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}

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

移动端适配

/* 移动端可能需要调整行数 */
@media (max-width: 768px) {
  .line-clamp-3 {
    -webkit-line-clamp: 2;
  }
}

与 title 属性配合

<div class="line-clamp-2" title="完整文本内容">
  这是一段很长的文本,可能会被截断显示...
</div>

面试要点

  1. 能够写出单行省略的完整代码(三个核心属性)
  2. 了解多行省略的 -webkit-line-clamp 方案
  3. 知道多行省略的兼容性问题和替代方案
  4. 理解 text-overflow 的生效条件
  5. 了解如何处理英文长单词的换行问题