Floating Vue Components
floating-vue is a Vue.js library for creating interactive floating UI elements such as tooltips, dropdowns, menus, and popovers. It is built upon the robust Floating UI library for precise and efficient positioning. The current stable version is 5.2.2, with active maintenance demonstrated by frequent patch and minor releases. A key differentiator is its comprehensive integration with Vue 3, providing both components (like VTooltip, VDropdown) and directives (like v-tooltip, v-close-popper) for declarative control over floating elements. The library ships with full TypeScript type definitions, enhancing developer experience and project reliability. It also offers powerful theming capabilities and flexible configuration options to adapt to various design systems.
Common errors
-
`FloatingVue` is not defined or `app.use` expects a plugin with an install method.
cause The `FloatingVue` plugin or its styles have not been correctly imported and registered in the Vue application entry point.fixEnsure you have `import FloatingVue from 'floating-vue'` and `import 'floating-vue/dist/style.css'` in your main application file, followed by `app.use(FloatingVue)` after creating your Vue app instance. -
[Vue warn]: Failed to resolve component: VTooltip (or VDropdown, VMenu)
cause The `VTooltip` (or other Floating Vue components) component is not globally registered, or not imported in the local component where it's being used.fixIf using a build setup, ensure `app.use(FloatingVue)` is called once. If using components directly in a SFC, `import { VTooltip } from 'floating-vue'` and add it to the `components` option, or use `<script setup>` for auto-import. -
`Element` is not defined on server (or similar SSR errors)
cause Floating Vue components or directives might try to access browser-specific `window` or `document` objects during server-side rendering, leading to errors.fixWrap Floating Vue components in a `<ClientOnly>` component if you are using Nuxt or similar SSR frameworks, or dynamically import them to ensure they only render on the client side. A fix for a specific instance of this was released in v5.0.1. -
Dropdown/Tooltip closes immediately or fails to open reliably when rapidly changing its `shown` prop or target.
cause Rapidly toggling the `shown` prop or switching targets without an adequate delay can sometimes prevent the popper from correctly re-initializing or closing/opening, especially if `disposeTimeout` is active or internal state transitions overlap.fixIntroduce a small delay (e.g., `nextTick` or a short `setTimeout`) between setting `shown = false` and `shown = true`, or when re-assigning a new target for the popper, to allow the internal closing/opening logic to complete. Consider using `recomputeAllPoppers()` after dynamic changes if issues persist.
Warnings
- breaking Version 5.0.0 was a re-bump of v2.0.0, primarily to resolve NPM tag issues, and officially announced 'no changes' compared to v2.0.0. However, the internal versioning history can be confusing, as subsequent patches like v5.0.3 introduced changes like `disposeTimeout` default values.
- breaking The default value of the `disposeTimeout` prop, which controls how long a popper instance persists after hiding, was changed in v5.0.3 from 0ms to the default transition duration. This could cause unexpected behavior where poppers remain in the DOM longer than anticipated.
- deprecated A deprecation notice for `VTooltip` and `VClosePopper` was added in v5.2.1. While the components and directives are still functional and present in the documentation, it indicates a potential future shift in recommended usage or API structure.
- breaking The `autohide` behavior, specifically on `mousedown` events, was altered and then reverted/made configurable in v5.2.1. Previously, `mousedown` might unexpectedly close poppers, which was then addressed by introducing `autoHideOnMousedown` in config.
- gotcha The package moved from `v-tooltip` to `floating-vue` and changed its underlying positioning library from `Popper.js` to `Floating UI`. This involved significant breaking changes in prop names, global configuration, CSS classes (now BEM-like with `v-popper` prefix), and the modifier API.
Install
-
npm install floating-vue -
yarn add floating-vue -
pnpm add floating-vue
Imports
- FloatingVue
const FloatingVue = require('floating-vue'); // CommonJS is not the primary import style for this ESM-first libraryimport FloatingVue from 'floating-vue'
- VTooltip
import VTooltip from 'floating-vue/src/components/VTooltip'; // Incorrect path, use direct named import from root
import { VTooltip } from 'floating-vue' - VDropdown
import { Dropdown } from 'floating-vue'; // 'Dropdown' is often confused, it's 'VDropdown'import { VDropdown } from 'floating-vue' - v-close-popper
<button v-close-popper>Close</button>
- recomputeAllPoppers
import FloatingVue, { recomputeAllPoppers } from 'floating-vue'; // recomputeAllPoppers is a separate utility importimport { recomputeAllPoppers } from 'floating-vue'
Quickstart
import { createApp, ref } from 'vue';
import FloatingVue from 'floating-vue';
import 'floating-vue/dist/style.css';
const App = {
setup() {
const message = ref('Hello Floating Vue!');
const count = ref(0);
setInterval(() => {
count.value++;
}, 2000);
const dynamicContent = `You have <b>${count.value}</b> new messages.`;
return {
message,
count,
dynamicContent
};
},
template: `
<div id="app" class="p-8 flex flex-col items-center space-y-4">
<h1 class="text-2xl font-bold">Floating Vue Basic Example</h1>
<VTooltip :distance="10">
<button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">Hover for Tooltip (Static)</button>
<template #popper>
<div class="p-2 bg-gray-700 text-white rounded shadow-lg">
{{ message }}
</div>
</template>
</VTooltip>
<VTooltip placement="right" :distance="10">
<button class="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600">Hover for Tooltip (Dynamic)</button>
<template #popper>
<div class="p-2 bg-gray-700 text-white rounded shadow-lg" v-html="dynamicContent"></div>
</template>
</VTooltip>
<VDropdown :distance="10">
<button class="px-4 py-2 bg-purple-500 text-white rounded hover:bg-purple-600">Click for Dropdown</button>
<template #popper>
<div class="p-4 bg-white rounded shadow-lg border">
<p class="mb-2">Dropdown Content</p>
<button v-close-popper class="px-3 py-1 bg-red-500 text-white rounded hover:bg-red-600">Close Me</button>
</div>
</template>
</VDropdown>
</div>
`,
};
const app = createApp(App);
app.use(FloatingVue);
app.mount('#app');