You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Tooltip参考元素始终保持在滚动容器内?

解决Vue3 + @floating-ui/vue Tooltip参考元素超出滚动容器时自动隐藏的问题

方法1:使用Floating UI内置的hide中间件指定滚动容器

Floating UI的hide中间件可以检测参考元素是否在指定根容器(即你的滚动容器)的可视范围内,自动返回isHidden状态,直接用来控制Tooltip的显示。

具体实现:

  1. 导入hide中间件
  2. 在useFloating配置中,将hide的root指向滚动容器DOM元素
  3. 通过返回的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 23:18:19