Overview
ResizeObserver composable for detecting when an element’s size changes. Perfect for responsive components and size-based rendering.
Features
- ResizeObserver API wrapper
- Pause/resume/stop functionality
- Automatic cleanup on unmount
- SSR-safe (checks SUPPORTS_OBSERVER)
- Hydration-aware
- Box model options (content-box/border-box)
Function Signature
function useResizeObserver(
target: MaybeElementRef,
callback: (entries: ResizeObserverEntry[]) => void,
options?: ResizeObserverOptions
): UseResizeObserverReturn
Parameters
callback
(entries: ResizeObserverEntry[]) => void
The callback to execute when the element’s size changes.
Call the callback immediately with current size.
Stop observing after first resize.
box
'content-box' | 'border-box'
default:"'content-box'"
Which box model to observe.
Return Value
Whether the observer is currently active.
Whether the observer is currently paused.
Stop observation and clean up.
Examples
Basic usage
import { ref } from 'vue'
import { useResizeObserver } from '@vuetify/v0'
const el = ref<HTMLElement>()
const width = ref(0)
const height = ref(0)
const { pause, resume, isPaused } = useResizeObserver(
el,
(entries) => {
const entry = entries[0]
if (entry) {
width.value = entry.contentRect.width
height.value = entry.contentRect.height
}
},
{ immediate: true }
)
Responsive component
<script setup>
import { ref, computed } from 'vue'
import { useResizeObserver } from '@vuetify/v0'
const containerRef = ref<HTMLElement>()
const width = ref(0)
useResizeObserver(
containerRef,
(entries) => {
width.value = entries[0]?.contentRect.width || 0
},
{ immediate: true }
)
const columns = computed(() => {
if (width.value < 600) return 1
if (width.value < 900) return 2
return 3
})
</script>
<template>
<div ref="containerRef" :class="`columns-${columns}`">
<!-- Content -->
</div>
</template>
Border-box sizing
useResizeObserver(
element,
(entries) => {
const { width, height } = entries[0]!.contentRect
console.log('Border box size:', width, height)
},
{ box: 'border-box' }
)
Pause and resume
const { pause, resume, isPaused } = useResizeObserver(
element,
handleResize
)
// Pause during heavy operations
pause()
performExpensiveCalculation()
resume()
Once mode
// Get initial size only
useResizeObserver(
element,
(entries) => {
const { width, height } = entries[0]!.contentRect
console.log('Initial size:', width, height)
},
{ once: true, immediate: true }
)
Convenience Function: useElementSize
function useElementSize(
target: MaybeElementRef
): UseElementSizeReturn
Returns reactive refs for element dimensions:
The width of the element in pixels.
The height of the element in pixels.
Example
import { ref, watchEffect } from 'vue'
import { useElementSize } from '@vuetify/v0'
const box = ref<HTMLElement>()
const { width, height } = useElementSize(box)
watchEffect(() => {
console.log('Box size:', width.value, 'x', height.value)
})
Responsive text sizing
<script setup>
import { ref, computed } from 'vue'
import { useElementSize } from '@vuetify/v0'
const containerRef = ref<HTMLElement>()
const { width } = useElementSize(containerRef)
const fontSize = computed(() => {
return Math.max(12, Math.min(24, width.value / 20))
})
</script>
<template>
<div ref="containerRef" :style="{ fontSize: `${fontSize}px` }">
Responsive text
</div>
</template>
Entry Properties
The size and position of the element’s content box.
The element being observed.
Use Cases
- Responsive components: Adjust layout based on container size
- Text sizing: Scale text to fit container
- Chart rendering: Update charts when container resizes
- Grid layouts: Recalculate column count based on available space
- Canvas sizing: Resize canvas to match container
- Virtual scrolling: Adjust viewport calculations
Notes
- Automatically stops observing when
once: true and a resize occurs
- Hydration-aware: defers setup until client-side hydration completes
- SSR-safe: returns valid API with
isActive: false when ResizeObserver is not supported
immediate option provides current size on first mount
useElementSize convenience function automatically uses immediate: true