在项目开发过程当中,常常会遇到溢出文本的省略问题。根据需求,能够把文本省略分为单行文本省略和多行文本省略两类。javascript
单行文本的省略,如今css样式 text-overflow
已经有兼容性很好的样式支持了。可是多行文本,目前支持webkit内核的css样式 -webkit-line-clamp
能够作到,但它针对火狐浏览器就行不通了。这就是本文要解决的问题。css
若是上网搜索【多行文本省略】,除了上文提到的css样式控制,找到的答案都是作固定位置的遮盖,并且能发现的是,目前几乎全部的博客都是这种方法(这大概是如今互联网技术博客的一个通病了,作原创的真的不多)。下面是这些方法的具体代码:html
方案一:webkit专属样式法java
div { /* 对容器自己作限制 */
display: -webkit-box; /* 弹性盒旧式语法 */
-webkit-box-orient: vertical; /* 通过我的实测,vertical或horizontal都没问题,只是必须设置该属性 */
-webkit-line-clamp: 2; /* 限制两行 */
overflow: hidden;
}
复制代码
方案二:css遮盖法node
p {
position: relative;
height: 40px;
line-height: 20px; /* 限制两行 */
overflow: hidden;
}
p:after { /* 对文本标签自己作限制 */
content: "...";
position: absolute;
bottom: 0;
right: 0;
background-color: #fff;
}
复制代码
这种方法只能说想固然地解决问题,实际上不少时候它的效果并不理想——有时候最后的文字会“犹抱琵琶半遮面”,有时候自己文字还不够长时就出现了,如图:git
这里是以上代码的一个演示:css解决多行文本省略演示 代码演示中case1没法体现效果。一样的代码,能够去张鑫旭大神的演示空间查看效果:-webkit-line-clamp下多行文字溢出点点点...显示实例页面程序员
当尝试用css解决不通时,就应该想到用js来解决。我找了不少网上的解决方案,有提到用插件的,也有提到上文css,但真的不多有提到用js的……并且这些解决方案的特色,上文也提到了,“天下文章一大抄”,每每还不提出原博客出处。github
这里提一下插件解决方案,主要是两个。一个是基于jQuery的dotdotdot,文档也很详细,可是license收费呀/(ㄒoㄒ)/~~;另外一个是Clamp.js,纯js插件,虽然免费可是没什么文档,并且做者也好几年没更新了(这种坑就会不少了)……综上,网上的插件都不符合个人心理预期。web
好了,回到js解决方案,既然靠别人不行,那就靠本身吧。可是,用js实现文本省略最大的难点就是:如何知道哪段文本是溢出的?或者说怎么找到溢出文本并去掉?浏览器
这里原理很简单,就是逐个增长文本字数,比较当时字数时文本的长度是否超过容器的长度。用jQuery来写也很简单,可是须要一些css样式作辅助,不然你根本达不到想要的效果。代码贴在下面:
#container {
border: 1px solid;
height: 90px;
width: 30px; // height 和 width 都必要
/*overflow: hidden;*/
overflow-wrap: break-word; // 设置文本溢出容器宽度时换行(但会溢出容器长度)
}
#content {
line-height: 30px; // 必要,控制文本行数。不然文本会被挤压,行数不定
}
复制代码
// jQuery 演示
var $container = $('#container')
var $content = $('#container .content')
var str = $content.text()
if ($content.height() > $container.height()) {
for (var i = 0; i <= str.length; i++) {
$content.text(str.slice(0,i))
if ($content.height() > $container.height()) {
$content.text(str.slice(0,i-2) + "..");
break;
}
}
}
//===================================================================
// 原生 JS 演示
var container = document.getElementById("container");
var content = container.firstElementChild;
var str = content.firstChild.nodeValue;
if (content.scrollHeight > container.offsetHeight) {
for (var i = 0; i <= str.length; i++) {
content.firstChild.nodeValue = str.slice(0,i);
//console.log(content.scrollHeight + ":" + container.offsetHeight);
if (content.scrollHeight > container.offsetHeight) {
content.firstChild.nodeValue = str.slice(0,i-2) + "..";
break;
}
}
}
复制代码
能够看出,原理是很简单的,重点是熟悉一些基础知识。这里贴上以上代码的演示:js解决多行文本省略的演示
若是只是想要解决问题代码的同窗,看到这里就ok了;若是想要再看我啰嗦一些东西,能够耐着性子继续看下去。
若是有同窗仔细比对两段代码,必定会有上面那个疑惑。事实上,DOM并无提供height属性。
可是,scrollHight
和 offsetHeight
又有什么区别呢?请看下图:
上图中,红框的高度大体体现了 scrollHeight
的高度。假如对外框设置 overflow: hidden
,红框会收缩至黑框内部,可是实际的 scrollHeight
仍是原红框的高度。
而 offsetHeight
和 clientHeight
差很少,都是反映元素表现的高度。这三个更详细的区别请看这个文档:JavaScrip 教程 / DOM / Element 节点
PS:通过本人实测,jQuery的 .height()
方法反映的是 scrollHeight
,本场景是足以应付的,可是一些特殊状况仍是须要用到DOM提供的。
到这里该讲的差很少都说完了,可是由于个人项目中多处用到多行文本的省略,每次都copy实在非程序员所为。因此,我将这个方法插入jQuery,做为扩展的方法。将代码贴出来,造福和我同样萌萌的新人~
/**
* jQuery自定义函数
*/
(function ($) {
/**
* 检查文字长度是否溢出,若是是则将溢出部分省略
*
* 注意:
* 文字自己容器需设置line-height
* 父物体容器需设置height和overflow-wrap: break-word(目前兼容性比较好的溢出换行样式)
*/
$.fn.checkOverflow = function (parentClass) {
$(this).each(function (id, el) {
var $this = $(el);
var $parent = $this.closest(parentClass);
if ($this.height() > $parent.height()) {
var parentHeight = $parent[0].offsetHeight;
var thisText = $this.text();
for (var i = 0; i <= thisText.length; i++) {
$this.text(thisText.slice(0, i));
if (parentHeight < $this[0].scrollHeight) {
var str_all_cn = true;
// 判断省略号取代的三个字符是否全为中文字符
thisText.slice(i-2).split('').forEach(function (c,id) {
if (thisText.slice(i-2).charCodeAt(id) <= 255) {
str_all_cn = false;
}
});
if (str_all_cn) {
$this.text(thisText.slice(0, i - 2) + "...");
} else {
$this.text(thisText.slice(0, i - 3) + "...");
}
break;
}
}
}
})
};
})(jQuery);
复制代码
虽然这个只是解决了实际项目开发中一个小得不能再小的问题,可是从头至尾写下来,我我的仍是从中收获了不少。因此说,写专栏一时爽,一直写一直爽~
最后,推荐一些在这个过程当中发现的颇有用的资料: