【CSS/JS】如何实现单行/多行文本溢出的省略(...)--绕过坑道的正确姿势

【CSS/JS】如何实现单行/多行文本溢出的省略(...)--绕过坑道的正确姿势

之前一直在博客园写作,最近几天才开的知乎专栏,才疏学浅, 谬误之处请不吝于评论区指教,谢谢大家。


文章目录

  • 单行文本溢出的省略
  • 从单行文本溢出省略到多行文本溢出省略
  • 多行文本溢出的省略(...)方案一 ---简单方便的解决方案
  • 多行文本溢出的省略(...)方案二 ---简单粗暴的解决方案
  • 多行文本溢出的省略(...)方案三 --简洁优雅的解决方案


写前端UI的朋友们也许都遇到过这样的问题:我们需要实现这样一个需求,在一个父级元素中隐藏一个可能过长的文本


这个文本可能是单行的:




也可能是多行的:



下面我就给大家展示如何简单或优雅地实现这种需求


单行文本溢出的省略


先上代码

<div style = 
    'width:400px;
     height:40px;
     border:1px solid red;'>
     <p style=
       'overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;'>
          这是一些文本这是一些文本这是一些文本这是一些文本这是一些文本
          这是一些文本这是一些文本这是一些文本这是一些文本这是一些文本
     </p>
</div>


demo:




关于overflow: hidden

这里我们需要注意到一点:这里的overflow并不是设置为父级元素div的属性,而是p标签的属性,需要和overflow的普通用法区分开来

  1. overflow:hidden的普通用法:用在块级元素(例如div)的外层隐藏内部溢出元素
  2. overflow: hidden的特殊用法:在上述例子中配合text-overflow: ellipsis;white-space: nowrap;实现p元素隐藏自身的溢出并设置(...)的效果


关于text-overflow: ellipsis;

这一属性依赖于overflow: hidden存在,只有设置了overflow:hidden它才是能够生效的,你可以把它看作overflow对于文本溢出隐藏的一种‘特殊样式’


关于white-space: nowrap

它的作用是让文本不换行,这是overflow:hidden和text-overflow:ellipsis生效的基础!没有它overflow:hidden和text-overflow:ellipsis无法生效!(在单行文本溢出省略这一案例中)


从单行文本溢出省略到多行文本溢出省略

许多同学可能会这样想:怎么实现多行文本省略呢?不是只要把white-space:nowrap去掉就可以了吗?( _(:3 」∠)_ 要是这么简单就好了...)

实践出真知,让我们来试一下,去掉CSS样式中的white-space:nowrap


demo:




这次,没能隐藏成功,那如果我们overflow:hidden是设在父级元素div中呢?

得到demo:



隐藏成功了,可你仍然看不到你想看到的那三个点


妥妥地失败了,嗯,没错,所以对于多行文本溢出的省略我们需要另辟蹊径了


多行文本溢出的省略(...)方案一 ---简单方便的解决方案


我们可以借助webkit的CSS扩展属性实现这一点:

<div style = 
    'width:400px;
     height:70px;
     border:1px solid red;'>
     <p style=
       'display: -webkit-box;//对象作为弹性伸缩盒子模型显示 
        -webkit-box-orient: vertical;//设置或检索伸缩盒对象的子元素的排列方式 
        -webkit-line-clamp: 2;//溢出省略的界限
        overflow:hidden;'//设置隐藏溢出元素
         >
        这是一些文本这是一些文本这是一些文本这是一些文本这是一些文本
        这是一些文本这是一些文本这是一些文本这是一些文本这是一些文本
     </p>
</div>


demo:





【注意】

  1. 四行CSS缺一不可!
  2. 因为这是webkit的CSS属性扩展,所以兼容浏览器范围是PC端的webkit内核的浏览器:chrome/safari/QQ浏览器/360/猎豹等以及绝大多数的移动端浏览器


多行文本溢出的省略(...)方案二 ---简单粗暴的解决方案


方案一固然最为简单,但其还存在着跨浏览器兼容的问题,于是人民群众们提出了一种简单粗暴的方式去实现通用的解决方案:给div固定高和宽,同时采用相对定位,与此同时对在div内放一个<p>...</p>对其使用绝对定位,定在右下角,同时设其背景颜色为白色就可以了:

<div style = 
    'position:relative;
     width:400px;
     height:45px;
     border:1px solid red;
     overflow:hidden;'>
     这是一些文本这是一些文本这是一些文本这是一些文本这是一些文本
     这是一些文本这是一些文本这是一些文本这是一些文本这是一些文本
     <p style = 'position:absolute;right:0;bottom:6px;margin:0;background:white'>...</p>
</div>

demo:




但方案二也有一些问题

1在文本没有溢出父级元素时也同样显示省略号:



2末尾处文本可能有被“裁剪”的副效果:



多行文本溢出的省略(...)方案三 --简洁优雅的解决方案


那么有没有更加优雅的解决方案,在没有溢出的时候不显示省略号(...),在溢出的时候隐藏并显示省略号呢?答案是有的!先看看我们最终实现的demo:


在文本没有溢出父级元素时:




文本溢出父级元素时:



下面是HTML和JS代码:

<div id='view' 
     style='border:1px solid red;
     width:200px;
     height:70px;
     overflow:auto'>
</div>


JS代码

s = '这是一个文本这是一个文本这是一个文本这是一个文本这是一个文本这是一个文本'
el = document.getElementById('view');
n = el.offsetHeight;
for(i=0; i<s.length; i++) {
  el.innerHTML = s.substr(0, i);
  if(n < el.scrollHeight) {
    el.style.overflow = 'hidden';
    el.innerHTML = s.substr(0, i-3) + '...';
    break;
   }
}


首先我们需要弄清楚offsetHeight和scrollHeight所表示的高度:


1溢出显示滚动条时:




2没有溢出时:



el = document.getElementById('view'); 
n = el.offsetHeight;

表示的是取到当前包裹文本的父级元素的高度

el.innerHTML = s.substr(0, i);

表示在for循环中取出长度递增的文段,例如:

'这'   --> '这是'   -->   '这是一'

当n < el.scrollHeight也就是 当前文本高度<滚动条内的内容的高度,代表着刚好达到溢出的界限,此时执行if内的语句

el.style.overflow = 'hidden';
el.innerHTML = s.substr(0, i-3) + '...'; 
break;

将父级元素view的overflow设置为hidden,并且将末尾的三个文字用...取代,同时跳出for循环


perfect! 这样我们就实现了优雅的解决方案


编辑于 2019-09-15

文章被以下专栏收录