As a developer building complex React dashboards for FinTech firms, I’ve often hit a common roadblock.
Standard CSS media queries are great, but sometimes you need the exact pixel width of a component to render a dynamic chart or a responsive data table.
Whether you are building a real-time stock ticker or a custom navigation bar, knowing the container size is crucial for a polished UI.
In this tutorial, I will show you exactly how to get a component’s width in React using the most reliable methods I use in production.
Why You Might Need a Component’s Width
While flexbox and grid handle most layouts, certain high-end UI components require programmatic width values.
For instance, if you are building a localized weather widget for a Chicago-based travel app, you might need to toggle between a compact and expanded view based on the div size.
I have also used these techniques to calculate the number of visible items in a horizontal scroll menu for a California-based e-commerce storefront.
Method 1: Use the useRef and useEffect Hooks
This is the easiest way to grab the width after the initial render. It is perfect for static elements that don’t change size after the page loads.
I typically use this when I need to initialize a third-party library, like a D3.js map, that requires a fixed width.
import React, { useRef, useEffect, useState } from 'react';
// Example: A Mortgage Calculator Container for a US Banking App
const MortgageWidget = () => {
const containerRef = useRef(null);
const [width, setWidth] = useState(0);
useEffect(() => {
if (containerRef.current) {
// offsetWidth includes borders and padding
const currentWidth = containerRef.current.offsetWidth;
setWidth(currentWidth);
console.log("Initial Widget Width:", currentWidth);
}
}, []);
return (
<div
ref={containerRef}
style={{
width: '100%',
maxWidth: '800px',
margin: '20px auto',
padding: '20px',
border: '1px solid #ddd',
backgroundColor: '#f9f9f9'
}}
>
<h2>US Home Loan Calculator</h2>
<p>Current Container Width: <strong>{width}px</strong></p>
<div style={{ height: '100px', background: '#004a99', color: 'white', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
{width > 500 ? "Desktop View: Showing Full Amortization Table" : "Mobile View: Showing Summary Only"}
</div>
</div>
);
};
export default MortgageWidget;I executed the above example code and added the screenshot below.

In this code, we attach a ref to the div. Once the component mounts, useEffect triggers, allowing us to read offsetWidth.
Method 2: Handle Window Resizes
If your users frequently flip their iPhones or resize their Chrome browsers, Method 1 will fail because it only runs once.
I remember building a real-time election map for a news outlet where the SVG had to scale perfectly as the user adjusted their window.
To solve this, we need to add an event listener to the window object.
import React, { useRef, useEffect, useState } from 'react';
const ResponsiveAdBanner = () => {
const bannerRef = useRef(null);
const [bannerWidth, setBannerWidth] = useState(0);
const updateWidth = () => {
if (bannerRef.current) {
setBannerWidth(bannerRef.current.getBoundingClientRect().width);
}
};
useEffect(() => {
// Set initial width
updateWidth();
// Add event listener for window resize
window.addEventListener('resize', updateWidth);
// Clean up the listener to prevent memory leaks
return () => window.removeEventListener('resize', updateWidth);
}, []);
return (
<div ref={bannerRef} style={{ width: '90%', margin: '0 auto', background: '#eee', padding: '15px' }}>
<h3>Texas State Fair - Early Bird Tickets</h3>
<p>The current width of this promotional banner is: {Math.round(bannerWidth)}px</p>
{bannerWidth < 400 ? (
<button style={{ width: '100%' }}>Buy Now</button>
) : (
<button style={{ padding: '10px 40px' }}>Secure Your Tickets Today</button>
)}
</div>
);
};
export default ResponsiveAdBanner;I executed the above example code and added the screenshot below.

Using getBoundingClientRect().width is often more precise than offsetWidth as it handles sub-pixel values and CSS transforms.
Method 3: The Modern Way with ResizeObserver
Window resize listeners are okay, but they are inefficient. They trigger even if the specific component doesn’t change size (e.g., if a sidebar collapses).
The ResizeObserver API is a game-changer. It watches the specific element rather than the whole window.
I used this extensively while building a modular dashboard for a logistics company in Seattle.
import React, { useState, useLayoutEffect, useRef } from 'react';
const DeliveryTracker = () => {
const [width, setWidth] = useState(0);
const targetRef = useRef(null);
useLayoutEffect(() => {
if (!targetRef.current) return;
const observer = new ResizeObserver((entries) => {
for (let entry of entries) {
// Use contentRect for the most accurate measurement
setWidth(entry.contentRect.width);
}
});
observer.observe(targetRef.current);
return () => observer.disconnect();
}, []);
return (
<div ref={targetRef} style={{ border: '2px dashed #333', padding: '20px', resize: 'horizontal', overflow: 'auto' }}>
<h4>FedEx Shipment Tracker (Drag corner to resize)</h4>
<p>Tracking ID: 12345-67890-USA</p>
<div style={{ fontSize: width < 300 ? '12px' : '18px', transition: '0.3s' }}>
Current Width: {Math.floor(width)}px
</div>
</div>
);
};
export default DeliveryTracker;I executed the above example code and added the screenshot below.

I prefer useLayoutEffect here because it fires synchronously after all DOM mutations. This prevents the “flicker” you sometimes see with useEffect.
Method 4: Create a Reusable useComponentSize Custom Hook
In a large-scale project, you don’t want to rewrite the observer logic ten times. Clean code is a priority for me, so I always abstract this into a custom hook.
Here is a robust hook I’ve used across multiple US-based SaaS projects.
import { useState, useLayoutEffect, useCallback } from 'react';
const useComponentSize = () => {
const [size, setSize] = useState({ width: 0, height: 0 });
const [node, setNode] = useState(null);
const ref = useCallback((newNode) => {
if (newNode !== null) {
setNode(newNode);
}
}, []);
useLayoutEffect(() => {
if (!node) return;
const measure = () => {
const { width, height } = node.getBoundingClientRect();
setSize({ width, height });
};
const observer = new ResizeObserver(() => measure());
observer.observe(node);
return () => observer.disconnect();
}, [node]);
return [ref, size];
};
// Usage Example: A real estate listing card for a Miami brokerage
const PropertyCard = () => {
const [componentRef, { width }] = useComponentSize();
return (
<div ref={componentRef} style={{ background: '#fff', boxShadow: '0 4px 8px rgba(0,0,0,0.1)', borderRadius: '8px' }}>
<img
src="https://images.unsplash.com/photo-1512917774080-9991f1c4c750"
alt="Miami Luxury Home"
style={{ width: '100%', height: width > 400 ? '300px' : '150px', objectFit: 'cover' }}
/>
<div style={{ padding: '15px' }}>
<h3>$2,450,000 - Luxury Villa</h3>
<p>Container Width: {Math.round(width)}px</p>
{width > 350 && <p>Located in the heart of South Beach, Florida.</p>}
</div>
</div>
);
};
export default PropertyCard;Using a callback ref instead of useRef ensures that the hook re-calculates correctly even if the underlying DOM node changes.
Method 5: Use getBoundingClientRect for One-Off Calculations
Sometimes you don’t need to track the width; you just need to know what it is at a specific moment, like when a user clicks a “Print Report” button.
I used this recently for a tax software application based in California to ensure the PDF generation layout matched the screen width.
import React, { useRef } from 'react';
const TaxReportGenerator = () => {
const reportRef = useRef(null);
const handlePrint = () => {
if (reportRef.current) {
const dimensions = reportRef.current.getBoundingClientRect();
alert(`The report width is ${dimensions.width}px. Optimizing for 1040-ES layout...`);
// Proceed with print logic
}
};
return (
<div style={{ padding: '30px', textAlign: 'center' }}>
<div ref={reportRef} style={{ border: '1px solid black', padding: '50px', marginBottom: '10px' }}>
<h1>2025 IRS Tax Summary</h1>
<p>This is a confidential document for US Taxpayers.</p>
</div>
<button onClick={handlePrint} style={{ backgroundColor: '#d32f2f', color: 'white', padding: '10px 20px', border: 'none', cursor: 'pointer' }}>
Generate Optimized Report
</button>
</div>
);
};
export default TaxReportGenerator;This method is lightweight because it avoids state updates and observers entirely.
Key Differences: offsetWidth vs. getBoundingClientRect
Choosing the right property is a common point of confusion.
offsetWidth returns an integer and includes the element’s padding, scrollbar, and border.
getBoundingClientRect().width returns a precise floating-point number and is usually what you want for high-precision layouts.
In my experience, if you are working with CSS transforms like scale(), getBoundingClientRect is the only one that returns the visually rendered width.
Getting the component width in React is a foundational skill for building truly responsive web applications.
Whether you use a simple ref or a complex ResizeObserver, always remember to clean up your listeners to keep your app performing smoothly.
You may also like to read:
- How to Refresh or Reload a Component in React
- How to Convert React Component to Web Component
- Build React Code Snippet Component
- How to Create a Retool Custom React Component

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.