如何让伪元素的宽度适应文字内容的同时受到最大宽度的限制,且在小于最大宽度时不自动换行,大于最大宽度时才换行?

作者站长头像
站长
· 阅读数 8

如何让伪元素的宽度适应文字内容的同时受到最大宽度的限制,且在小于最大宽度时不自动换行,大于最大宽度时才换行?这是用React封装Tooltip组件时遇到的一个问题,我的思路是给tooltip下的第一个子元素添加::before伪元素,当hover时tooltip出现。tooltip组件的定义如下:

import "./tooltip.css"


function Tooltip({ title, children }) {
  if (Array.isArray(children)) {
    throw new Error("Tooltip can only have one direct subcomponent");
  }
  window.c = children;

  return (
    <>
      <div className="tooltip-container" style={{
        "--tooltipContent": `"${title}"`
      }
      }>
        {children}
      </div>
    </>
  )
}


export default Tooltip;

tooltip.css代码如下:

.tooltip-container {
  --tooltipContent: "2024年2月2日, 128次浏览";
  --tooltipMargin: 15px;
  --tooltipVisibility: hidden;
  --tooltipScale: 0.1;
  --tooltipOpacity: 0.2;
}

.tooltip-container>:first-child {
  border: 1px dashed red;
  position: relative;
  box-sizing: border-box;
}

.tooltip-container>:first-child:hover {
  cursor: pointer;
  --tooltipVisibility: visible;
  --tooltipOpacity: 1;
}

.tooltip-container>:first-child::before {
  color: white;
  background-color: #000;
  display: inline-block;
  content: var(--tooltipContent);
  position: absolute;
  padding: 8px;
  border-radius: 5px;
  max-width: 300px;
  width: fit-content;
  white-space: nowrap;
  left: 50%;
  bottom: calc(100% + var(--tooltipMargin));
  transform: translateX(-50%);
  visibility: var(--tooltipVisibility);
  opacity: var(--tooltipOpacity);
  transition: all 0.15s;
  z-index: 9999;
}

.tooltip-container>:first-child::after{
  content: "";
  border: 5px solid transparent;
  border-top-color: #000;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: calc(-1 * var(--tooltipMargin));
  visibility: var(--tooltipVisibility);
  opacity: var(--tooltipOpacity);
  transition: all 0.15s;
  z-index: 9999;
}

组件使用方式如下:

function App() {


  return (
    <>
      <Tooltip title={"tooltip title"}>
        <div
          style={{ width: "200px", height: "200px" }}
        >

        </div>
      </Tooltip>
    </>
  )
}

我想要的效果是,类似与ant design的tooltip, 当文字较少时正常显示,即使有分词也不换行,当文字较多时在最大宽度处换行。

目前我的问题是,若使用white-space: nowrap;,则文字较少时正常,但文字超过最大宽大后不会换行而是被隐藏, 如下图所示:如何让伪元素的宽度适应文字内容的同时受到最大宽度的限制,且在小于最大宽度时不自动换行,大于最大宽度时才换行?

若使用word-wrap: break-word;overflow-wrap: break-word;, 则会在文字较少并遇到分词处自动换行,如下图所示:如何让伪元素的宽度适应文字内容的同时受到最大宽度的限制,且在小于最大宽度时不自动换行,大于最大宽度时才换行?

想求助各位大佬该怎么实现?

回复
1个回答
avatar
test
2024-06-23
  • 首先我们需要知道元素的初始width是多少,才能计算width: fit-content

    • 当最大内容宽度大于初始的width时,就会换行,计算结果就是这个width的大小。
    • 当最大内容宽度小于初始的width时,计算结果就是最大内容宽度。
  • 当初始的width小于max-width的时候,且最大内容宽度大于max-width时,它在初始宽度大小时就换行了,所以不会在max-width时换行。伪元素上left:50%,使得它的初始width大小只有父元素宽度的一半了,要小于设置的max-width,所以就提早换行了。(你去掉left:50%之后就会在最大宽度处换行了)
  • 大多数的tooltip的实现都是将tooltip-toggletooltip分别在两个元素上实现。tooltip采用绝对定位,相对于body,此时初始宽度就比较大了,就不用担心初始宽度小于max-width了。之后采用popper.js之类的库计算inset,将其定位在tooltip-toggle周围。而你的实现将tooltip放在了tooltip-toggle中了,感觉不太好,虽然它更好计算位置了,但是遇到了你所说的问题,with: fit-content, max-width, position: absolute在一起使用的时候达不到预期的效果。
回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容