@floating-ui/react
是一个专为 React 设计的库,用于创建浮动元素(如 tooltip、popover、dropdown 等)的位置定位和智能摆放。适配 React 的 API 和 Hook,如 useFloating()
。
它能解决的问题
浮动元素常见问题:
- 不知道如何精准定位(相对于目标元素)
- 避免被遮挡(视口边缘、滚动时不隐藏等)
- 自动调整位置(比如空间不足时从下变上)
@floating-ui/react
会根据目标元素的位置、视口情况自动计算最优位置,并返回一系列用于定位的参数和 style。
安装
npm install @floating-ui/react
基本用法
下面是一个最简单的 tooltip 示例:
import React, { useState } from 'react';
import { useFloating, offset, flip, shift, autoUpdate } from '@floating-ui/react';
export default function Tooltip() {
const [open, setOpen] = useState(false);
const {
x,
y,
reference,
floating,
strategy,
update,
refs,
} = useFloating({
placement: 'top',
middleware: [offset(8), flip(), shift()],
whileElementsMounted: autoUpdate,
});
return (
<div>
<button
ref={reference}
onMouseEnter={() => setOpen(true)}
onMouseLeave={() => setOpen(false)}
>
Hover me
</button>
{open && (
<div
ref={floating}
style={{
position: strategy,
top: y ?? 0,
left: x ?? 0,
backgroundColor: 'black',
color: 'white',
padding: '6px 12px',
borderRadius: '4px',
zIndex: 9999,
}}
>
Tooltip content
</div>
)}
</div>
);
}
可以,你只需要在浮动层(弹出框)中也监听 onMouseEnter
/ onMouseLeave
,让它和按钮共享控制逻辑,就能避免移动过去时关闭。
修改为支持鼠标移到弹出层里不关闭
import React, { useState } from 'react';
import { useFloating, offset, flip, shift, autoUpdate } from '@floating-ui/react';
export default function Tooltip() {
const [open, setOpen] = useState(false);
const [isHovering, setIsHovering] = useState(false);
const {
x,
y,
reference,
floating,
strategy,
} = useFloating({
placement: 'top',
middleware: [offset(8), flip(), shift()],
whileElementsMounted: autoUpdate,
});
const handleMouseEnter = () => {
setOpen(true);
setIsHovering(true);
};
const handleMouseLeave = () => {
setIsHovering(false);
// 延迟关闭,避免快速移动时闪烁
setTimeout(() => {
if (!isHovering) setOpen(false);
}, 100);
};
return (
<div>
<button
ref={reference}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
Hover me
</button>
{open && (
<div
ref={floating}
style={{
position: strategy,
top: y ?? 0,
left: x ?? 0,
backgroundColor: 'black',
color: 'white',
padding: '6px 12px',
borderRadius: '4px',
zIndex: 9999,
}}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
Tooltip content
</div>
)}
</div>
);
}
效果说明
- 鼠标进入 button 或弹出框时,
setOpen(true)
- 鼠标移出时,会延迟一点时间判断是否还在浮动层,如果不在才
setOpen(false)
- 这样可以避免用户快速从按钮移入弹出层时被误关闭
常用 Middleware
offset(px)
:浮动元素距离参考元素的偏移量。flip()
:如果原来的位置空间不够,则自动翻转方向。shift()
:防止浮动元素溢出视口。
高级功能(可选)
autoUpdate()
:自动监听滚动或窗口大小变化并重新计算位置。- 支持虚拟元素(如 chart 中的 tooltip)。
- 与 Floating UI 核心库高度兼容,可按需自定义。