单行文本溢出显示省略号
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
众所周知的方法,既然是溢出,那么就需要父元素确定宽度,另外无论是单行还是多行文本,最好加上word-break: break-all
来确保字母也能顺利换行。
多行文本溢出
目前我了解的比较好的实现方式主要有两种。
- css实现(网上随便都能搜到)
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
-webkit-line-clamp
表示文本需要显示多少行,-webkit-box-orient
指定子元素的排列方式,只有值为vertical
时才能使-webkit-line-clamp
生效。
关于兼容性问题
根据caniuse的查询结果:
-webkit-line-clamp
属性在edge上从17版本(2018.4发布)开始支持,firefox从68版本(2019.6发布)开始支持,IE全系列不支持,其它主流浏览器支持尚可。
-webkit-box-orient
属性在edge上86版本之前需要改为-ms-
前缀,87版本开始(2020.11发布)和chrome相同,firefox则需要改为-moz-
前缀,IE继续全系列不支持。
所以如果对兼容性要求不高的话可以直接使用css属性。
import $clamp from 'clamp-js/clamp';
//Single line
$clamp(dom, {clamp: 1});
//Multi-line
$clamp(dom, {clamp: 3});
clamp
属性代表需要多少行再省略,其它的属性可以查阅说明或者源码。
clamp-js
的实现原理:
看了一下它的源码,实现过程大概是这样的,如果浏览器兼容-webkit-line-clamp
,则直接为dom元素加上上面的css属性,如果不兼容,则使用js截取字符串,如果没有特殊字符(空格、小数点、横线等)则去掉字符串最后一位并加上省略号判断字符串高度是否小于设定高度(每行高度默认等于行高,如果line-height为normal则使用1.2*fontSize),不小于则递归继续截取字符串,直到获得高度满足要求的字符串。
最后使用如下字符串测试:'史蒂夫·乔布斯(英语:ABCDEFGHIJK)😁😱,是aaabbbdddddddsfsdfsdfsdfsdfsdf,苹果公司的联合创始人之一,曾任董事长及首席执行官职位,NeXT创办人及首席执行官,也是皮克斯动画的创办人并曾任首席执行官,2006年为华特迪士尼公司的董事会成员。'
在IE9+,safari,chrome,firefox,edge上面均运行正常,很完美。
PS:最开始我是想参悟iview的实现方法的,从控制台上猜测它的实现方法大概是计算出给定行数内的字符串数量然后截取并添加省略号,无奈最后怎么算都差一个条件,只好作罢。(弱弱的喊一句,开源万岁)
附上我自己的思考过程,不知道有没有大佬能把iview的实现方法搞出来
data() {
return {
wordsNum: '123456789012', // 12---100px宽时正好显示完整的字符串长度
wordsLowerLetters: 'abcdefgabcdef', // 13
wordsUpperLetters: 'ABCDEFGHIJK', // 11
wordsChinese: '任董事长及首席', // 7
wordsSymbol: '!@#$%^&*()_+', // 12
wordsSymbol2: '!()——《》', // 7
wordsJapanese: 'いきものがかり', // 7
}
}
......
/**
* @description: 根据内容宽度和fontsize获取省略号之前的字符串长度(由于不知道规定行数内的字母数量所以暂时无法计算)
* @param {Stirng} str 内容字符串
* @param {Number} lineNum 需要保留的行数
* @param {Number} width 容器[内容]的宽度
* @param {Number} fontSize 容器内文本的字体大小
* @return {*}
*/
getStringLength(str, lineNum, width, fontSize = 14) {
// 近似计算:小写字母和数字一个字符占半个fontsize的宽度,其他的一个字符占一个fontsize的宽度
// 按照小写字母和数字为一个字符串长度,其它为两个字符串长度来计算
const unitNumberPerLine = Math.floor((width / fontSize) * 2); // 每一行的最小字符串长度(以小写字母和数字为最小单位)
const unitNumberInNeed = unitNumberPerLine * lineNum; // 可以容纳的最小字符串总长度
const lowerStrReg = /[a-z0-9]/g; // 匹配小写字母和数字
const lowerStrLength = str.match(lowerStrReg).length; // 小写字母和数字的长度
const otherStrLength = str.length - lowerStrLength; // 其他字符串的长度
const strUnitLength = otherStrLength * 2 + lowerStrLength; // 按照最小单位计算出来的字符串所占总长度
}
网友评论