如何让Tooltip参考元素始终保持在滚动容器内?
解决Vue3 + @floating-ui/vue Tooltip参考元素超出滚动容器时自动隐藏的问题
方法1:使用Floating UI内置的hide中间件指定滚动容器
Floating UI的hide中间件可以检测参考元素是否在指定根容器(即你的滚动容器)的可视范围内,自动返回isHidden状态,直接用来控制Tooltip的显示。
具体实现:
- 导入
hide中间件 - 在
useFloating配置中,将hide的root指向滚动容器DOM元素 - 通过返回的
isHidden值控制Tooltip的显示隐藏
代码示例:
<script setup> import { ref } from 'vue' import { useFloating, hide } from '@floating-ui/vue' const scrollContainer = ref(null) const reference = ref(null) const floating = ref(null) const { x, y, strategy, isHidden } = useFloating(reference, floating, { middleware: [ hide({ root: () => scrollContainer.value, // 绑定滚动容器为检测根节点 }), ], }) </script> <template> <div ref="scrollContainer" class="scroll-container"> <button ref="reference">Hover to show tooltip</button> <teleport to="body"> <div ref="floating" :style="{ position: strategy, top: `${y}px`, left: `${x}px` }" v-if="!isHidden" class="tooltip" > Tooltip content here </div> </teleport> </div> </template> <style scoped> .scroll-container { overflow-y: auto; height: 300px; border: 1px solid #eee; } .tooltip { background: #333; color: #fff; padding: 6px 12px; border-radius: 4px; pointer-events: none; } </style>
方法2:手动使用Intersection Observer监听可见性
如果需要更自定义的检测逻辑,可以直接用浏览器原生的Intersection Observer API,监听参考元素在滚动容器内的可见状态,进而控制Tooltip显示。
代码示例:
<script setup> import { ref, onMounted, onUnmounted } from 'vue' import { useFloating } from '@floating-ui/vue' const scrollContainer = ref(null) const reference = ref(null) const floating = ref(null) const isReferenceVisible = ref(true) const { x, y, strategy } = useFloating(reference, floating) onMounted(() => { const observer = new IntersectionObserver( ([entry]) => { // 当参考元素在滚动容器内可见比例超过10%时显示Tooltip isReferenceVisible.value = entry.isIntersecting }, { root: scrollContainer.value, threshold: 0.1 } ) reference.value && observer.observe(reference.value) onUnmounted(() => observer.disconnect()) }) </script> <template> <div ref="scrollContainer" class="scroll-container"> <button ref="reference">Hover to show tooltip</button> <teleport to="body"> <div ref="floating" :style="{ position: strategy, top: `${y}px`, left: `${x}px` }" v-if="isReferenceVisible" class="tooltip" > Tooltip content here </div> </teleport> </div> </template>
补充说明
之前teleport到body或滚动容器无效的原因是:Floating UI默认以整个视口作为检测范围,而非你的滚动容器。通过上述两种方法指定滚动容器为检测根节点后,才能准确判断参考元素是否在滚动容器的可视区域内,从而实现自动隐藏。
内容的提问来源于stack exchange,提问作者Kanstantin Loz
相关产品推荐
相关产品推荐

