useElementSize
Layout/Viewport
A React hook that tracks element dimensions in real-time using ResizeObserver, perfect for responsive layouts and dynamic UI adjustments.
Demo
Try resizing the container below to see how elements adapt to the available space:
Container Width
0px
Container Height
0px
Font size: 16px
Responsive Text
This text block smoothly fades and scales based on container width.
1
2
3
4
Grid Columns
1
Scale
0.00
Opacity
-1.00
Tip: Drag the right edge of the container to resize it.
Installation
npm install @thibault.sh/hooks
Usage
import { useElementSize } from '@thibault.sh/hooks/useElementSize';
import { useRef } from 'react';
function ResponsiveElement() {
const elementRef = useRef<HTMLDivElement>(null);
const { width, height } = useElementSize(elementRef);
return (
<div ref={elementRef} className="resize overflow-auto p-4 border">
<div>Width: {Math.round(width)}px</div>
<div>Height: {Math.round(height)}px</div>
{/* Content */}
</div>
);
}
API
Returns
Object containing current element width and height
Features
- ✓Real-time Updates
Automatically updates when element dimensions change using ResizeObserver
- ✓Performance Optimized
Uses efficient ResizeObserver API with proper cleanup
- ✓Zero Layout Shift
Measures content size without affecting layout
- ✓SSR Compatible
Safely handles server-side rendering scenarios
Responsive Grid Example
import { useElementSize } from '@thibault.sh/hooks/useElementSize';
import { useRef } from 'react';
function ResponsiveGrid({ items }: { items: Array<any> }) {
const containerRef = useRef<HTMLDivElement>(null);
const { width } = useElementSize(containerRef);
// Calculate optimal number of columns based on container width
const columns = Math.max(1, Math.floor(width / 300)); // 300px min column width
return (
<div ref={containerRef} className="w-full">
<div
className="grid gap-4"
style={{ gridTemplateColumns: `repeat(${columns}, 1fr)` }}
>
{items.map((item, index) => (
<div key={index} className="p-4 border rounded">
{/* Item content */}
</div>
))}
</div>
</div>
);
}
Dynamic Text Sizing Example
import { useElementSize } from '@thibault.sh/hooks/useElementSize';
import { useRef } from 'react';
function ResponsiveText() {
const containerRef = useRef<HTMLDivElement>(null);
const { width } = useElementSize(containerRef);
// Scale font size based on container width
const fontSize = Math.max(16, Math.min(width / 20, 48));
return (
<div ref={containerRef} className="w-full resize overflow-auto p-4 border">
<p style={{ fontSize: `${fontSize}px` }}>
This text will scale with the container width!
</p>
</div>
);
}
Aspect Ratio Container Example
import { useElementSize } from '@thibault.sh/hooks/useElementSize';
import { useRef, useEffect, useState } from 'react';
function AspectRatioContainer({ ratio = 16 / 9 }) {
const containerRef = useRef<HTMLDivElement>(null);
const { width } = useElementSize(containerRef);
const [height, setHeight] = useState(0);
useEffect(() => {
setHeight(width / ratio);
}, [width, ratio]);
return (
<div ref={containerRef} className="w-full">
<div
style={{ height: `${height}px` }}
className="bg-gray-100 transition-all duration-200"
>
{/* Content that maintains aspect ratio */}
</div>
</div>
);
}