设置text-overflow: ellipsis;后,通过鼠标移入的时候判断是否超长,并作出反馈提示(悬停title等)。首先需要明确元素的几个属性:
Element.clientWidth:
对于内联元素和没有CSS的元素,该属性为零;否则,它是元素的内部宽度(以像素为单位)。它包括padding,但不包括border, margin和垂直滚动条(如果存在)。
Element.scrollWidth:
一个元素的内容的宽度,其中包括溢出内容(在屏幕上不可见的部分:overflow)。
scrollWidth值等于元素所需的最小宽度,以便在不使用水平滚动条的情况下适合视口中的所有内容。宽度的测量方法与clientWidth相同:它包括元素的pading,但不包括其border,margin和垂直滚动条(如果存在)。它还可以包括伪元素的宽度,例如::before或::after。如果元素的内容不需要水平滚动条就可以容纳,scrollWidth则等于clientWidth
HTMLElement.offsetWidth
一个元素的布局宽度,包括任何border,padding和垂直滚动条(如果已渲染)。但不包括伪元素的宽度,例如::before或::after。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.div1 {
height: 100px;
width: 100px;
border: 2px solid;
margin: 10px;
padding: 9px;
}
.div2 {
height: 100px;
width: 100px;
overflow: auto;
border: 2px solid;
margin: 10px;
padding: 9px;
}
</style>
<script>
window.onload = function () {
const ODiv1 = document.getElementsByClassName('div1')[0]
const ODiv2 = document.getElementsByClassName('div2')[0]
const ODiv2inner = document.getElementsByClassName('div2inner')[0]
console.log('[div1 clientWidth , div2 clientWidth]:', ODiv1.clientWidth, ODiv2.clientWidth)
console.log('[div1 scrollWidth , div2 scrollWidth]:', ODiv1.scrollWidth, ODiv2.scrollWidth)
console.log('[div1 offsetWidth , div2 offsetWidth]:', ODiv1.offsetWidth, ODiv1.offsetWidth)
console.log('height相关')
console.log('[div1 clientHeight , div2 clientHeight]:', ODiv1.clientHeight, ODiv2.clientHeight)
console.log('[div1 scrollHeight , div2 scrollHeight]:', ODiv1.scrollHeight, ODiv2.scrollHeight)
console.log('[div1 offsetHeight , div2 offsetHeight]:', ODiv1.offsetHeight, ODiv2.offsetHeight)
console.log('div2inner width相关')
console.log('div2inner clientWidth:', ODiv2inner.clientWidth)
console.log('div2inner scrollWidth:', ODiv2inner.scrollWidth)
console.log('div2inner offsetWidth:', ODiv2inner.offsetWidth)
}
</script>
</head>
<body>
<div class="div1">div1元素</div>
<div class="div2">
<div class="div2inner">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</div>
</div>
</body>
</html>
复制代码
这里div2 scrollWidth等于602为:div2inner scrollWidth加上div2的padding-left,padding-right失效;处理这种情况一般可以设置div2inner的display: inline-block;margin: 0 10px;达到同样效果。或者div2inner只设置超长部分隐藏overflow: hidden;
我们需求是超长部分隐藏然后做提示,所以应该设置内部元素overflow: hidden;然后判断内部元素的scrollWidth + 外部元素的padding是否大于外部元素的offsetWidth;当大于的话做出title等反馈提示。使用react及antd组件库封装组件:
import { FC, useState } from 'react';
import classnames from 'classnames';
import { Tooltip } from 'antd';
import { TooltipPlacement } from 'antd/lib/tooltip';
import styles from './index.less';
interface IProps {
value: string;
className?: string;
placement?: TooltipPlacement;
stepWidth?: number; // padding等需要减除的数值
}
const TextLong: FC<IProps> = ({ value, className, placement, stepWidth }) => {
const [visible, setVisible] = useState(false);
const onMouseOver = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const currentWidth = e.currentTarget.scrollWidth + (stepWidth ?? 0);
const parentWidth = e.currentTarget.parentElement?.offsetWidth || 0;
if (currentWidth > parentWidth) {
setVisible(true);
}
};
const onMouseLeave = () => {
setVisible(false);
};
return (
<Tooltip
title={value}
placement={placement}
visible={visible ? undefined : false}
>
<div
className={classnames(styles.content, className)}
onMouseOver={onMouseOver}
onMouseLeave={onMouseLeave}
>
{value}
</div>
</Tooltip>
);
};
export default TextLong;
复制代码
// index.less
.content {
text-overflow: ellipsis;
overflow : hidden;
white-space : nowrap;
}
复制代码