判断文本是否溢出
问题
需求:当一个div的内容过多时,显示省略号,并提供一个显示更多的按钮;如果内容较少,正常展示不提供按钮。
分析:以上问题的本质就在于,如何判断div的内容溢出了
(为了方便,方案采用vue的写法)
方案一
方案一为Determine if an HTML element's content overflows中的最高赞回答,主要思想是对比元素的el.clientWidth和el.scrollWidth,如果scrollWidth较大,说明溢出了,否则没溢出。
<div class='content' ref="content">长长的内容长长的内容</div>
<button v-if="showBtn">显示</button>
const el = this.$refs.content
this.showBtn = el.clientWidth < el.scrollWidth
window.addEventListener('resize', () => {
this.showTest = el.clientWidth < el.scrollWidth
})
.test{
width:10%;
background: #ccc;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
为了测试方便,以上demo加上了改变窗口大小的resize函数,可以发现div宽度增大时,文本不溢出不显示按钮,div宽度缩小时,文本溢出显示按钮
stackoverflow的回答下,有人反映此方案在某些浏览器会出现,文本溢出了,但clientWidth与scrollWidth相等。于是有人提到了另一个方案
方案二
方案二位 HTML text-overflow ellipsis detection的最高赞回答,主要是将div克隆一份但不显示(visibility:hidden),比较两者的宽度,如果副本的宽度大于元素本身的宽度,则表示溢出,否则未溢出
<div class='content' ref="content">长长的内容长长的内容</div>
<div class='content-copy' ref="contentCopy">长长的内容长长的内容</div>
<button v-if="showBtn">显示</button>
const el = this.$refs.content
const elCopy = this.$refs.contentCopy
this.showBtn = el.clientWidth < elCopy.clientWidth
console.log(el.clientWidth, elCopy.clientWidth)
window.addEventListener('resize', () => {
this.showBtn = el.clientWidth < elCopy.clientWidth
})
.content{
display: inline-block;
width:10%;
background: #ccc;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.content-copy{
display: inline-block;
visibility: hidden;
}
这里要注意一点,此方案中元素不能为block,因为这样eleCopy的宽度会为父元素的100%,而不是由内容撑开的宽度;也不能为inline,因为这样没有width,无法比较;因此将元素设为inline-block
应用场景
在列表中,会经常出现这种溢出的情况。比如我遇到的问题:在列表的某一行文字发生溢出时,hover才展示提示。
通过设置一个变量,在触发当前mouserenter事件时,动态计算是否展示提示
const
<div className="list">
<Tooltip title={isOverflow ? '测试测试测试' : ''}>
<span
onmouseEnter={(e) => {
const target = e.target as HTMLElement;
setIsOverflow(target.scrollWidth - target.clientWidth > 0);
}}>测试测试测试<span>
</Tooltip>
<Tooltip title={isOverflow ? '测试测试测试' : ''}>
<span
onmouseEnter={(e) => {
const target = e.target as HTMLElement;
setIsOverflow(target.scrollWidth - target.clientWidth > 0);
}}>测试测试测试<span>
</Tooltip>
</div>
小结
以上2种方案都可以实现判断文本是否溢出,虽然思想有所不同,但其实本质是一样的:都是通过对比文本实际的宽度和显示省略号时的宽度,所以可以从这一点出发,再多多思考有没有其他解决方案。