写在前面
text-overflow是css中用于设置如何向用户显示隐藏的溢出内容的属性,这个属性多用于超出元素范围后现实省略号。
对于省略号的触发条件,CSS3文档描述为当元素宽度小于实际宽度时触发,那么我们就会想到可以通过offsetWidth和scrollWidth来判断是否触发了省略号的显示
但实际上真的是这样的吗?
发现问题
很显然,通过offsetWidth和scrollWidth来判断是否触发了省略号的显示是不够精准的。这个问题的发现来自于antd的一个Issues:Typography.paragraph can't display tooltip #49110
它描述Typography.paragraph在某些特定情况下,无法触发提示组件tooltip
问题分析
借助#49110 这个Issues来看一下这个问题是怎么产生的
// >>>>> Native ellipsis
React.useEffect(() => {
const textEle = typographyRef.current;
if (enableEllipsis && cssEllipsis && textEle) {
// https://github.com/ant-design/ant-design/issues/49110
// Check whether text-overflow attribute is blocked
setIsCssTextOverflow(textEle.offsetWidth < textEle.scrollWidth);
const currentEllipsis = cssLineClamp
? textEle.offsetHeight < textEle.scrollHeight
: textEle.offsetWidth < textEle.scrollWidth;
if (isNativeEllipsis !== currentEllipsis) {
setIsNativeEllipsis(currentEllipsis);
}
}
}, [enableEllipsis, cssEllipsis, children, cssLineClamp, isNativeVisible, ellipsisWidth]);
由源码可以发现,触发是否显示tooltip组件的参数currentEllipsis是根据textEle.offsetWidth < textEle.scrollWidth这个条件触发的,也就是元素宽度 小于 实际宽度,问题就在于offsetWidth 和 scrollWidth真的能代表元素宽度 和 实际宽度吗
通过Range对象和getBoundingClientRect()方法获取了更精准的元素宽度和实际宽度我们可以发现,offsetWidth 和 scrollWidth进行了舍入操作,所以offsetWidth 和 scrollWidth应该表达的是近似值而非准确值,而对于底层实现,text-overflow则是依据准确值来判断是否显示省略号,那么在offsetWidth 和 scrollWidth相等的情况下,就有可能发送这种元素宽度和实际宽度有极小差异的情况,这也是导致offsetWidth 和 scrollWidth不能作为text-overflow是否显示省略号的判断条件的原因
如何解决
通过问题分析我们可以发现,这种极小概率出现的情况只能发生在offsetWidth 和 scrollWidth相等的情况,那么我们只需要在offsetWidth 小于 scrollWidth的区间内去触发text-overflow属性就可以了,也就是说,当offsetWidth 大于或等于 scrollWidth时,无论是视觉上还是底层差异上,都不需要使用text-overflow属性,具体通过一个state去判断是否显示带有text-overflow属性的类就好了
评论区