文本超出范围显示省略号

1.需求场景一:单行文本

1
2
3
4
5
.needEllipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}

2.需求场景二:多行文本

上面这种情况无法用于多行文本中的换行,因为我们使用white-space:nowrap用于规定段落中的文本不进行换行;并且text-overflow必须和overflow以及white-space进行搭配才可实现单行文本换行;对于多行文本超出显示省略号来说,稍微麻烦一点,可以使用js,css也行。css的解决方案如下所示(注:只适用于webkit内核浏览器,微信小程序可使用该方式):

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

需要注意的是overflow:hidden不是必须的,但是考虑到有大于MAX_DISPLAY_LINE_Number行文本的话,还是最好加上。如果不设置的话,那么如果某段text对应5行文本的话,设置的-webkit-line-clamp的值是3的话,那么第3行文本的末尾就是省略号,而第四行文本会照常显示出来。

诚如上面所说,这种情况只是适用于webkit内核的浏览器,那么使用css处理的话有没有其他的什么兼容处理方式呢?答案是有的,比如说下面这种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
.multiEllipsis {
position: relative;
line-height: 1.5em;
height: 4.5em;
overflow: hidden;
}
.multiEllipsis::after {
position: absolute;
content: '...';
font-weight: bold; /*可不加,用于加粗*/
bottom: 0;
right: 0;
width: 30px; /*可不加,不过为了呈现出最好的效果的话还是加一下,width的大小为整数个字体的宽度,以避免出现半个字体的情况*/
background: #fff; /*设置背景,用来遮盖字体,背景颜色视情况而定*/
}

上面这种处理方式还是挺完美的,足以处理大部分场合下的多行文本溢出显示省略号了。

3.多行文本处理方式之使用js

使用js的思路,利用js获取到限制文本的box的宽度,获取文本的fontSize,获取文本,遍历文本,利用fontSize获取每个字体的宽度,将宽度进行累加,一旦超过box的宽度*所需要显示行数,则停止遍历,此时筛选出来的子串就是所能够显示的最多文本,接着利用innerText给挂载到DOM元素上。对于使用这种方式来说,知识点在于:获取css(有可能是内联样式,也有可能不是);计算每个字体的宽度;下面先介绍一下如何获取css属性值:利用js获取某个元素element的css值有下面几种方法,1.element.style;2.IE:element.currentStyle[‘attr’];3.window.getComputedStyle(element, null).getPropertyValue[attr]。区别:第一种方法只能够获取内联样式;第二种以及第三种获取到的是最终应用在box上面的样式。因此,一般使用window.getComputedStyle来查询css,如下所示:

1
2
3
4
5
6
7
const getCssProperty = (element, attr) => {
if (element.currentStyle) { // 兼容IE
return element.currentStyle[attr];
} else {
return window.getComputedStyle(element, null).getPropertyValue(attr); // null表示并不是获取伪元素之类的
}
}

计算字体的宽度可以用下面的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const computeFontWidth = (font, fontSize) => {
let result, width;
if (/[a-zA-Z]/.test(font)) {
width = 0.7;
} else if (/[0-9]/.test(font)) {
width = 0.55;
} else if (/\./.test(font)) {
width = 0.27;
} else if (/-/.test(font)) {
width = 0.325;
} else if (/[\u4e00-\u9fa5]/.test(font)) { //中文匹配
width = 1;
} else if (/\(|\)/.test(font)) {
width = 0.373;
} else if (/\s/.test(font)) {
width = 0.25;
} else if (/%/.test(font)) {
width = 0.8;
} else {
width = 1;
}
result = width * fontSize;
return result;
}

将text挂载到dom上:

1
2
3
<p class="container">
测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本测试文本
</p>
1
2
3
4
5
6
7
8
9
10
.container {
width: 100px;
height: 100px;
position: relative;
font-size: 15px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border: 1px solid #000;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const showStr = (query, maxRow) => {
let p = document.getElementsByClassName(query)[0];
const str = p.innerText; // 获取文本
let showStr; // 需要显示的文本
let fontW = 0, endIndex = 0;
let width = getCssProperty(p, 'width'), fontSize = getCssProperty(p, 'font-size'); // 单位都是'px'
width = width.substring(0, width.length - 2), fontSize = fontSize.substring(0, fontSize.length - 2);

for (let i in str) {
fontW += computeFontWidth(str[i], fontSize);
if (fontW >= maxRow * width) {
endIndex = i;
break;
}
}

showStr = str.substring(0, endIndex - 2) + '...'; /*不一定是减2*/
p.innerText = showStr;
}
showStr('container', 3);

4.微信小程序之button样式设置

有些情况下,我们既想要语义化而使用button按钮,但是同时又希望样式符合普通的view,这个时候就需要稍微做一下处理,button默认样式具有padding-left以及padding-right,以及border,关键还是border,设置border:none;还不行,如果想要完全去除边框的话,那么应该怎样做:button::after {border:none;}