useMeasure

Real-time element dimension tracking using ResizeObserver.

300px

Resize Me

W: 0pxH: 0px
0 × 0

Usage

import { useMeasure } from 'usehooks-ts'
 
export default function Component() {
  const [ref, { width, height }] = useMeasure()
 
  return (
    <div ref={ref}>
      I am {width}px wide and {height}px tall
    </div>
  )
}

API

const [ref, rect] = useMeasure<E>()

Type Parameters

ParameterDefaultDescription
EHTMLElementThe type of the HTML element to measure

Return Values

NameTypeDescription
refRefObject<E>React ref to attach to the target element
rectMeasureResultObject containing dimension properties

MeasureResult Interface

interface MeasureResult {
  width: number
  height: number
  top: number
  left: number
  bottom: number
  right: number
  x: number
  y: number
}

Hook

import { useState, useRef, useLayoutEffect, useEffect } from 'react'
 
export interface MeasureResult {
  width: number
  height: number
  top: number
  left: number
  bottom: number
  right: number
  x: number
  y: number
}
 
const defaultState: MeasureResult = {
  x: 0,
  y: 0,
  width: 0,
  height: 0,
  top: 0,
  left: 0,
  bottom: 0,
  right: 0,
}
 
const isBrowser = typeof window !== 'undefined'
const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect
 
export function useMeasure<E extends HTMLElement = HTMLElement>() {
  const ref = useRef<E>(null)
  const [rect, setRect] = useState<MeasureResult>(defaultState)
 
  useIsomorphicLayoutEffect(() => {
    if (!ref.current) return
 
    const observer = new ResizeObserver(([entry]) => {
      if (entry) {
        setRect(entry.contentRect)
      }
    })
 
    observer.observe(ref.current)
 
    return () => {
      observer.disconnect()
    }
  }, [])
 
  return [ref, rect] as const
}