CSS
在某乎热榜页有一个很有意思的布局,这里的标题会制约内容的行数,所以文本超出是不定行的。详细规则如下:

  1. 整个容器高度是固定的,标题和内容总共 3 行
  2. 标题最多2行,超出省略
  3. 内容由剩余空间决定,如果标题占2行,则内容超出1行省略;如果标题占1行,则内容超出2行省略

是不是很灵(离)活(谱)的交互?可以充分利用页面空间,保证标题和内容都能展示出来,示意如下
CSS巧妙实现文本"不定行数"截断 - 图1
看了下原站的实现,是通过 js 判断标题高度,然后动态添加一个类名实现的。不过呢,经过一番琢磨,这里也是可以纯 CSS 实现的,一起来看看吧

一、标题超出省略

假设有这样一段 HTML

  1. <div class="section">
  2. <h3 class="title">LGD 在 TI10 放猛犸,RNG 在 S7 放加里奥最后都输了,哪个更让你愤怒失望?</h3>
  3. <p class="excerpt">猛犸是对面的绝中绝,大家都知道,并且之前扳回两局已经证明了,当lgd选择ban掉猛犸,或者自己抢掉猛犸时,对面完全不是对手。</p >
  4. </div>

标题的规则是超出2行省略,这个简单,直接用-webkit-line-clamp 实现

  1. .title{
  2. overflow: hidden;
  3. display: -webkit-box;
  4. -webkit-line-clamp: 2;
  5. -webkit-box-orient: vertical;
  6. }

超出2行就会自动省略了
CSS巧妙实现文本"不定行数"截断 - 图2

二、内容自适应行数

由于整个高度是固定的,如果让内容部分自适应剩余空间是不是就实现了呢?提到自适应剩余空间,可以马上想到 flex 布局,所以可以这样来实现:

  1. .section{
  2. display: flex;
  3. overflow: hidden;
  4. height: 72px;/*定一个高度*/
  5. flex-direction: column;
  6. }
  7. .excerpt{
  8. flex: 1; /*自适应剩余空间*/
  9. overflow: hidden;
  10. }

这样借助flex: 1;overflow: hidden;就几乎实现了想要的效果,如下
CSS巧妙实现文本"不定行数"截断 - 图3
已经很完美,只是现在超出还没有省略号,接着往下看

三、不定行超出省略

一般情况,-webkit-line-clamp适用于行数确定的情况下,现在行数不定,有时是 1 行,有时是 2 行,如何处理呢?

1. 右下角环绕效果

首先添加一个伪元素,设置右浮动

  1. .excerpt::before{
  2. content: '...';
  3. float: right;
  4. }

CSS巧妙实现文本"不定行数"截断 - 图4
很明显省略号目前是在右上角的,现在需要挪到右下角来,之前的操作是通过一个浮动元素把这个省略号挤下来,但是需要额外的占位元素
这里再介绍一种新的方式,借助 CSS shapes 布局实现!
首先,将省略号高度撑满,并居下对齐,可以用 flex 实现

  1. .excerpt::before{
  2. content: '...';
  3. float: right;
  4. height: 100%;
  5. display: flex;
  6. align-items: flex-end;
  7. }

CSS巧妙实现文本"不定行数"截断 - 图5
这样省略号虽然到了右下角,但是上面的部分也被挤走了,没有达到环绕的效果。这时就可以用 shapes 布局了。
这里仅仅只需要利用到 shape-outside:inset()就可以了,表示以自身为边界,然后上、右、下、左四个方向分别向内缩进的距离。比如这里需要缩进到靠近省略号位置,所以

  1. .excerpt::before{
  2. /*其他样式**/
  3. shape-outside: inset(calc(100% - 1.5em) 0 0);
  4. }

效果如下
CSS巧妙实现文本"不定行数"截断 - 图6
去除背景,可以看到省略号完美的环绕在右下角
CSS巧妙实现文本"不定行数"截断 - 图7

2. 自动隐藏省略号

现在还有一个问题,需要文本较少时隐藏省略号,该如何实现呢?可以试试 “CSS 障眼法”
简单来说,就是用一个足够大的色块盖住省略号,设置绝对定位后,色块是跟随内容文本的,所以在文字较多时,色块也跟随文本挤下去了,实现如下

  1. .excerpt::after{
  2. content: '';
  3. position: absolute;
  4. width: 999vh;
  5. height: 999vh;
  6. background: #fff;
  7. }

原理示意如下
CSS巧妙实现文本"不定行数"截断 - 图8
个别极端情况可能会遮挡不住,比如
CSS巧妙实现文本"不定行数"截断 - 图9
没关系,可以随便找个东西补上,比如 box-shadow,往左下角偏移一点就可以了

  1. .excerpt::after{
  2. content: '';
  3. position: absolute;
  4. width: 999vh;
  5. height: 999vh;
  6. background: #fff;
  7. box-shadow: -2em 2em #fff; /*左下的阴影*/
  8. }

CSS巧妙实现文本"不定行数"截断 - 图10
设置和底色相同的颜色后,最终的效果如下
CSS巧妙实现文本"不定行数"截断 - 图11
这样就实现了某乎的交互效果。
CSS巧妙实现文本"不定行数"截断 - 图12