多行省略从此不再难搞

317 阅读8分钟

CSS 解决多行省略的方案有很多种,本篇过滤了一些仅适用于一定会出现省略的情况,主要针对项目中比较常见的不确定行数的情况整理了 4 种方法,并且梳理了在什么情况下建议选择哪个方案。

需要兼容 PC 不?

“...” 就好还是需要自定义?

“...” 带渐变遮罩 OK 吗?

需要自适应高度吗?

问完这四个问题,选择一个方案。

方案 1:最简单的 -webkit-line-clamp

在线地址:-webkit-line-clamp

优点:

  • 简单易用,马上上手
  • 自适应高度

缺点:

  • 省略符不能自定义
  • 需要 PC 兼容就血崩,比较适合移动端
.ell-multi(@line: 2) {
    display: -webkit-box;
    -webkit-line-clamp: @line;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

方案 2:很有想法的 float

在线地址:很有想法的float

优点:

  • 兼容性强,全世界都支持 float
  • 省略符拓展性强,想怎么搞就怎么搞

缺点:

  • 不能自适应高度,会被设计师打
  • 第一次用需要认真理解一下原理,很难受
  • 省略符需要带底色,不适合背景复杂的区域,会穿帮

下面就针对第二个缺点,把实现过程解释一下,避免下次还难受。

1、层级很简单,一个盒子中有三个元素。我们先给三个元素都加上浮动,并且通过颜色看看这三个元素的位置。

<div class="ell-box">
  <div class="ell-box__text">CSS自定义属性?听着怎么那么神奇呢,属性还可以自定义,那不是可以放肆地玩耍?我自己定义的属性浏览器都能认识?CSS自定义属性?听着怎么那么神奇呢,属性还可以自定义,那不是可以放肆地玩耍?我自己定义的属性浏览器都能认识?</div>
  <div class="ell-box__placeholder"></div>
  <div class="ell-box__more">...展开</div>
</div>
/* 包裹层 */
.ell-box {
    position: relative;
    width: 400px;
    /* 确定高度 */
    height: 60px;  
    /* 为了方便看暂时不 overflow: hidden */
}
.ell-box__text {
    float: right;
    font-size: 14px;
    line-height: 20px;
    width: 100%;
    background-color: rgba(255, 244, 94, 0.5); 
    /* 黄色 */
}
.ell-box__placeholder {
    float: right;
    width: 60px;
    /* 等于包裹层高度 */
    height: 60px;
    background-color: rgba(243, 33, 33, 0.54);
    /* 红色 */
}
.ell-box__more {
    float: right;
    width: 60px;
    height: 20px;
    line-height: 20px;
    text-align: right;
    font-size: 14px;
    background-color: rgba(40, 62, 233, 0.5); 
    /* 紫色 */
}

2、上面的表现符合我们的预期,黄色、红色、紫色块依次从右边开始排布,现在我们调整一下位置。

/* more 和 placehoder 的宽度为 60px */
.ell-box__text {
    margin-left: -60px;
}

黄色有 margin-left 之后,就给了 红色 空间,可以排在一排。

黄色 的高度小于 红色 的高度时,例如文字显示 2 行,此时第一排的高度为 红色 的高度,所以排在后面的 紫色 不能挤进第一排,只能屈居第二排。

黄色 的高度大于 红色 的高度时,例如文字显示 4 行,此时第一排的高度被 黄色 的高度撑开,所以排在后面的 紫色 就能挤进所谓的和 黄色 同排。

3、也就是说当 黄色 需要省略 or 不需要省略的时候,紫色 的位置是不一定的。这样我们就有操作的空间了,嘿嘿嘿。

.ell-box__more {
    position: relative;
    /* 距离左边宽度 100% 的距离 */
    left: 100%; 
    /* 再往左往上回 */
    transform: translate(-100%, -100%);
}

4、最后修饰一下,加上隐藏和渐变背景(参考页面背景色)。

.ell-box {
    overlfow: hidden;
}
.ell-box__more {
    background-image: linear-gradient(270deg, #FFFFFF 48%, rgba(255, 255, 255, 0.87) 74%, rgba(255, 255, 255, 0) 100%);
}

方案 3: 自适应高度的 float

上面的 float 方案其实挺好的,但是很多时候 我们 设计师有自适应高度的需求,该怎么办呢?

这里的矛盾点在于,省略符的展示魔法需要定高,而自适应高度则不能定高,看起来水火不容。

这里提供一种思路:需要渲染两份文案,其中,真实展示的文案自由撑开高度,外层仅限制最大高度,这样就满足自适应高度的需求,而省略符的展示需要一个定高的绝对定位区域来辅助。

实现的效果还是不错的,但是多渲染了一份文案,总感觉还不是很完美,欢迎大家提出更好的想法~

<div class="ell-box">
    <!-- 真实展示的文案 -->
    <div class="ell-box__text">CSS自定义属性?听着怎么那么神奇呢,属性还可以自定义,那不是可以放肆地玩耍?我自己定义的属性浏览器都能认识?CSS自定义属性??</div>
    <!-- 用于撑开高度展示“more"的文案 -->
    <div class="ell-box__abs">
        <div class="ell-box__text">CSS自定义属性?听着怎么那么神奇呢,属性还可以自定义,那不是可以放肆地玩耍?我自己定义的属性浏览器都能认识?CSS自定义属性??</div>
        <div class="ell-box__placeholder"></div>
        <div class="ell-box__more">...展开</div>
    </div>
</div>
/* 核心修改 */
.ell-box {
    /* 包裹层改为自动高度,仅设置最大高度 */
    max-height: 60px;
    overflow: hidden;
}
.ell-box__abs {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 60px;
}
.ell-box__abs ..ell-box__text {
    color: transparent;
}

在线地址:自适应高度的float

对比方案 2,优点就是可以自适应高度,但是缺点也很突出,就是需要多渲染一份不可见的文案。

方案 4:魔法升级的 float + -webkit-line-clamp

如果设计师接受不了渐变的处理,或者该区域的背景颜色复杂的话,那么可以尝试一下下面这个结合方案,给你一个截断+透明的自定义省略符

在线地址:魔法升级的float+-webkit-line-clamp

这个效果基于CSS的多行省略中的方案进行优化,因为在学习的过程中发现原来的方案有一定的问题(使用-webkit-line-clamp的元素无法撑开完整高度),导致无法实现上述效果。

现在看看改进后的方案:

<div class="ell-box">
    <!-- 展示部分 -->
    <div class="ell-box__text">
        <div class="ell-box__inner inline">CSS自定义属性?听着怎么那么神奇呢,属性还可以自定义,那不是可以放肆地玩耍?我自己定义的属性浏览器都能认识?CSS自定义属性??
        </div>
    </div>
    <!-- 自定义省略符展示部分 -->
    <div class="ell-box__fake">
        <div class="ell-box__inner fake">CSS自定义属性?听着怎么那么神奇呢,属性还可以自定义,那不是可以放肆地玩耍?我自己定义的属性浏览器都能认识?CSS自定义属性??</div>
        <div class="ell-box__abs">
          <div class="ell-box__placeholder"></div>
          <div class="ell-box__more">... [详情]</div>
        </div>
    </div>
</div>

划重点啦!! 这个方案虽然稍显复杂,但是只要理解了两个点就可以实现了,两个点分别是上述两个部分。

我们先看第一部分,这部分要实现的效果是,展示文案中给自定义省略的地方空出位置

.ell-box__text {
    display: -webkit-box; /* 设置 3 行省略 */
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical; 
    font-size: 50px; /* 设置省略号的字号,也就是我们自定义省略符的宽度 */
    line-height: 0; /* 重置一些参数 */
    letter-spacing: 0; /* 重置一些参数 */
    color: transparent; /* 原来的省略号不显示 */
    color: read; /* 用做实验,我们先设置为红色 */
}
.ell-box__inner {
    /* 重置正常显示的文案字号/颜色等等 */
    font-size: 14px;
    line-height: 20px;
    color: #000;
    vertical-align: top;
    letter-spacing: 0;
}
.ell-box__inner.inline {
    display: inline;
}

这里为了更好理解,先把省略号颜色设置为红色,而文字包裹层的字号则为省略号所占的宽度,所以只要把省略号设置为透明色,我们就给自定义省略留出了空位。

继续看第二部分,这部分要实现的效果是,让自定义省略符放在预期位置,这里利用的也是float的原理。

这一部分也是绝对定位的元素,内部文案撑开高度,然后再嵌一层绝对定位的元素,left: 50%。第二层内元素即为蓝色、红色、紫色块依次 float: right 的布局,当蓝色块的高度随着文案被撑开到大于 3 行的高度时,紫色块就会排到展示区域的右下角。

再把自定义省略符的紫色块向上挪一下位置就完美了。

最后把伪装的文字设置为透明,两部分结合起来就是上面的效果啦。

体验小优化

1、无论是 float 方案还是结合方案,自定义的省略符一般都是靠右对齐的,那么多行省略的文案最好也能靠边对齐,视觉上会比较整齐。

.text {
    text-align: justify;
}

2、如果内容含有英文的话,英文单词换行也会导致视觉不对齐,可以考虑单词内换行,但是可读性也会下降,就看个人需求啦。

.text {
    word-break: break-all;
}

在线地址:demo

最后简单带一下单行省略

.single-line-ellipsis {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

在线 demo

总结

序号 方案 优点 缺点
1 -webkit-line-clamp 简单易用 / 自适应高度 不兼容 PC ie
2 float 兼容性好 / 可自定义 定高 / 省略符带渐变背景
3 float + 两份文案 可自定义 / 自适应高度 省略符带渐变背景
4 float + -wekit-line-clamp + 两份文案 可自定义 / 自适应高度 / 省略符背景透明 不兼容 PC ie