useContentSize
The size of an element's content box, in whole pixels, kept current with a ResizeObserver. useMeasuredWidth is the same for the width alone.
tsx
import { useContentSize, useMeasuredWidth } from '@basmilius/react-ui';tsx
import { useState } from 'react';
import { useContentSize, useMeasuredWidth } from '@basmilius/react-ui';
export default function UseContentSizeDemo() {
const [measure, size] = useContentSize();
const [measureWidth, width] = useMeasuredWidth();
const [wide, setWide] = useState(false);
return (
<div className="flex w-full flex-col items-center gap-3">
<div
ref={measure}
className="grid h-24 place-items-center rounded-lg border border-dashed border-border-strong text-xs text-text-muted"
style={{ width: wide ? '100%' : '50%' }}
>
{size.width} by {size.height}
</div>
<div ref={measureWidth} className="h-2 w-3/4 rounded-full bg-accent-soft">
<div className="h-2 rounded-full bg-accent" style={{ width: Math.round(width * 0.4) }} />
</div>
<button type="button" className="focus-ring rounded-md text-xs text-accent" onClick={() => setWide(!wide)}>
{wide ? 'Narrow the box' : 'Widen the box'}
</button>
</div>
);
}Both answer a callback ref and the size. Put the ref on the element to measure:
tsx
const [measure, { width, height }] = useContentSize();
return <div ref={measure}>{width > 0 && <Plot width={width} height={height} />}</div>;The size is rounded, so a frame fitted into the space lands on whole pixels too. A chart that draws in real pixels, rather than stretching a view box, uses the width to keep every line sharp. The size is 0 by 0 until the element is there.
ContentSize ({ width, height }) is an exported type.