超长自动隐藏(ellipsis),并显示title,不超长时不显示title

设置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>
复制代码

image.png
这里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;
}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享