Vue Resize Observer Directive
Vue Resize Observer is a lightweight plugin that provides a Vue directive, `v-resize`, to easily detect and react to resize events on any DOM element within a Vue component. It leverages the native `ResizeObserver` browser API for efficient size change detection without the performance overhead of traditional window resize listeners or polling. The package supports both Vue 2 (version `2.0.16` is the latest stable for Vue 2) and Vue 3, with separate installation instructions (`vue-resize-observer@next` for Vue 3). While not explicitly stated, the `@next` tag indicates active development for Vue 3 compatibility, suggesting a potentially faster release cadence for the Vue 3 branch. Its primary differentiator is the direct integration of the `ResizeObserver` API into a straightforward Vue directive, simplifying responsive layouts and element-specific size management.
Common errors
-
ReferenceError: ResizeObserver is not defined
cause The `ResizeObserver` API is not available in the current JavaScript runtime environment (e.g., older browser, Jest test environment, or Node.js during SSR).fixInstall a `ResizeObserver` polyfill for unsupported browsers or Jest. For SSR, ensure code utilizing `ResizeObserver` is executed only on the client-side using conditional rendering or dynamic imports with `ssr: false`. -
TypeError: Cannot read properties of undefined (reading 'use')
cause Attempting to use `Vue.use()` with a Vue 3 application instance created by `createApp()`. In Vue 3, `use` is an instance method, not a static method on the global Vue object for a specific app instance.fixFor Vue 3, call `use` on your application instance: `const app = createApp(App); app.use(VueResizeObserver);`. For Vue 2, `Vue.use(VueResizeObserver)` is correct. -
Failed to resolve directive: resize
cause The `v-resize` directive was not properly registered or imported. This could be due to incorrect global installation or missing local registration.fixEnsure `app.use(VueResizeObserver)` (Vue 3) or `Vue.use(VueResizeObserver)` (Vue 2) is called before mounting your app, or register it locally in your component's `directives` option: `directives: { 'resize': VueResizeObserver }`. Check that the import path is correct.
Warnings
- gotcha Vue 2 and Vue 3 versions require different installation commands. Installing the wrong version can lead to compatibility issues or errors. Vue 2 uses `vue-resize-observer`, while Vue 3 requires `@next` tag.
- breaking Vue 3 changed how global plugins are installed. `Vue.use()` is deprecated for Vue 3 applications using `createApp()`. Using the static `Vue.use` with a Vue 3 app instance will lead to errors.
- gotcha The `ResizeObserver` API, which this plugin relies on, is not available in all browser environments (e.g., older browsers) or in server-side rendering (SSR) environments. Using it without a polyfill or conditional rendering in such environments will result in a `ReferenceError`.
- gotcha The `ResizeObserver loop completed with undelivered notifications` warning in the console indicates that a resize event handler is synchronously triggering another resize event, potentially leading to an infinite loop.
Install
-
npm install vue-resize-observer -
yarn add vue-resize-observer -
pnpm add vue-resize-observer
Imports
- VueResizeObserver
import { VueResizeObserver } from "vue-resize-observer";import VueResizeObserver from "vue-resize-observer";
- VueResizeObserver
const { VueResizeObserver } = require("vue-resize-observer");const VueResizeObserver = require("vue-resize-observer"); - resize
directives: { 'v-resize': VueResizeObserver }import VueResizeObserver from "vue-resize-observer"; // ... in a component options object: directives: { 'resize': VueResizeObserver }
Quickstart
import { createApp, defineComponent, ref, onMounted } from 'vue';
import App from './App.vue';
import VueResizeObserver from 'vue-resize-observer';
// main.ts or app.ts
const app = createApp(App);
app.use(VueResizeObserver); // Globally install the v-resize directive
app.mount('#app');
// App.vue (or any other component)
<template>
<div
class="resizable-box"
v-resize="onBoxResize"
style="width: 50%; min-width: 200px; height: 200px; border: 2px solid #3498db; background-color: #ecf0f1; resize: both; overflow: auto; display: flex; flex-direction: column; align-items: center; justify-content: center; font-family: sans-serif; box-sizing: border-box; padding: 10px;"
>
<p>Resize this element!</p>
<p>Width: {{ width }}px</p>
<p>Height: {{ height }}px</p>
</div>
<p style="margin-top: 20px; font-family: sans-serif; color: #555;">Drag the bottom-right corner to change its size.</p>
</template>
<script lang="ts">
export default defineComponent({
name: 'ResizeDemo',
setup() {
const width = ref(0);
const height = ref(0);
const onBoxResize = (entry: ResizeObserverEntry) => {
// The entry object provides details about the resize event
width.value = Math.floor(entry.contentRect.width);
height.value = Math.floor(entry.contentRect.height);
console.log(`Box resized: W: ${width.value}, H: ${height.value}`);
};
// Initial size capture on mount (ResizeObserver will also trigger on first render)
onMounted(() => {
// You might need a ref to the element if you want its initial size
// directly, but v-resize will also call onBoxResize on first render.
});
return {
width,
height,
onBoxResize,
};
},
});
</script>
<style>
/* No specific styles needed beyond inline ones for quickstart */
</style>