A React component and hook for automatically resizing iframes based on their content
npm install react-responsive-iframe




A lightweight, TypeScript-ready React component and hook for automatically resizing iframes based on their content. Perfect for embedding responsive content that needs to adapt to its container. Solve iframe height issues, prevent content overflow, and create seamless user experiences.
Keywords: React iframe, responsive iframe, auto-resize iframe, dynamic iframe height, iframe content detection, React iframe component, TypeScript iframe, iframe resizer, iframe height adjustment, cross-origin iframe
- ๐ Automatic Resizing: Automatically adjusts iframe height and width based on content
- ๐ฑ Responsive Design: Supports multiple calculation methods for different use cases
- ๐ง TypeScript Support: Full TypeScript definitions included
- ๐ฏ Flexible Configuration: Customizable responsive behavior and options
- ๐ Security: Built-in origin checking for secure cross-origin communication
- โก Performance: Event-based resizing (no continuous intervals)
- ๐จ Easy Integration: Simple API that works with any React project
- ๐ No Initial Height Jump: Optionally hide the iframe until the correct height is calculated (see hideUntilResized)
- ๐ Content Change Detection: Automatically detects content addition and removal
- ๐ Multiple Calculation Methods: Choose the best height calculation for your use case
This React responsive iframe package is perfect for:
- ๐ Document Embedding: Embed PDFs, Google Docs, or other documents that need dynamic sizing
- ๐ Dashboard Widgets: Create responsive dashboard components with embedded content
- ๐ Form Embedding: Embed external forms that change height based on content
- ๐ฅ Video Players: Embed video players that need responsive sizing
- ๐ฑ Mobile Applications: Create mobile-friendly iframe experiences
- ๐ Cross-Origin Content: Safely embed content from different domains
- ๐ Content Management: Embed dynamic content that changes frequently
- ๐จ Portfolio Websites: Showcase projects in responsive iframe containers
- ๐ Analytics Dashboards: Embed analytics tools with automatic resizing
- ๐ง Developer Tools: Create responsive developer tool interfaces
| Feature | Traditional Iframe | React Responsive Iframe |
| ---------------------- | --------------------------------- | ----------------------------------- |
| Height Management | โ Fixed height, content overflow | โ
Automatic height adjustment |
| Content Detection | โ No content change detection | โ
Detects content addition/removal |
| Performance | โ Continuous polling | โ
Event-based resizing |
| User Experience | โ Scrollbars, layout shifts | โ
Smooth, seamless experience |
| Responsive Design | โ Fixed dimensions | โ
Adapts to content and screen |
| TypeScript Support | โ No type safety | โ
Full TypeScript definitions |
| Security | โ Basic security | โ
Origin checking and validation |
| Integration | โ Manual implementation | โ
Simple React component API |
``bash`
npm install react-responsive-iframe
or
`bash`
yarn add react-responsive-iframe
See it in action! Visit our interactive demo to explore all features:
The demo showcases:
- โ
Before vs After comparison with traditional iframes
- โ
Content addition/removal with automatic height adjustment
- โ
Parent-child communication examples
- โ
Different calculation methods for various use cases
- โ
Performance optimizations and responsive behavior
`jsx
import { ResponsiveIframe } from "react-responsive-iframe";
function App() {
return (
width="100%"
height={300}
onResized={(dimensions) => {
console.log("Iframe resized:", dimensions);
}}
/>
$3
If you don't set an explicit
height, the iframe will start at a default height (e.g., 300px) and "jump" to the correct height after the first resize. To avoid this, use the hideUntilResized prop:`jsx
src="https://example.com"
width="100%"
responsiveOptions={{ minHeight: 300, autoResize: true }}
hideUntilResized
/>
`- The iframe will be hidden until the first resize event is received, then shown at the correct heightโno visible jump!
$3
`jsx
import { useIframeResizer } from "react-responsive-iframe";function IframeContent() {
const { resize, sendMessage, isInitialized } = useIframeResizer({
heightCalculationMethod: "bodyScroll",
autoResize: true,
});
return (
Iframe Content
Status: {isInitialized ? "โ
Connected" : "โณ Connecting..."}
This content will automatically resize the parent iframe.
);
}
`๐ API Reference
$3
#### Props
| Prop | Type | Default | Description |
| ------------------- | ------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------ |
|
src | string | - | The URL of the iframe content |
| width | string \| number | - | Initial width of the iframe |
| height | string \| number | - | Initial height of the iframe |
| responsiveOptions | ResponsiveIframeOptions | {} | Configuration options for responsive behavior |
| onResized | (dimensions: {height: number, width: number}) => void | - | Callback when iframe is resized |
| onMessage | (message: any) => void | - | Callback for messages from iframe |
| onInit | (iframe: HTMLIFrameElement) => void | - | Callback when iframe is initialized |
| hideUntilResized | boolean | false | If true, hides the iframe until the first resize event is received, preventing the initial height jump |#### Responsive Options
`typescript
interface ResponsiveIframeOptions {
// Height calculation method
heightCalculationMethod?:
| "bodyScroll"
| "bodyOffset"
| "documentElementScroll"
| "documentElementOffset"
| "max"
| "min"
| "grow"
| "lowestElement"; // Width calculation method
widthCalculationMethod?: "scrollWidth" | "offsetWidth" | "max" | "min";
// Resizing behavior
tolerance?: number; // Minimum change in pixels before triggering resize
autoResize?: boolean; // Enable/disable automatic resizing
// Security
checkOrigin?: boolean | string[]; // Check message origin for security
// Size constraints
maxHeight?: number; // Maximum height limit
minHeight?: number; // Minimum height limit
maxWidth?: number; // Maximum width limit
minWidth?: number; // Minimum width limit
// Additional options
sizeWidth?: boolean; // Enable width resizing
scrolling?: boolean; // Enable/disable scrolling
}
`$3
#### Parameters
`typescript
interface IframeChildResizerOptions {
// Calculation methods
heightCalculationMethod?: HeightCalculationMethod;
widthCalculationMethod?: WidthCalculationMethod; // Behavior options
autoResize?: boolean;
manualOnly?: boolean; // Manual-only mode (no automatic resizing)
// Constraints
minHeight?: number;
maxHeight?: number;
minWidth?: number;
maxWidth?: number;
tolerance?: number;
// Callbacks
onParentMessage?: (message: any) => void;
}
`#### Returns
`typescript
{
sendMessage: (message: any) => void;
resize: (customHeight?: number, customWidth?: number) => void;
scrollTo: (x: number, y: number) => void;
scrollToOffset: (x: number, y: number) => void;
isInitialized: boolean;
}
`๐ฏ Advanced Examples
$3
`jsx
import { ResponsiveIframe } from "react-responsive-iframe";function AdvancedExample() {
return (
Advanced Responsive Iframe
src="https://example.com"
width="100%"
height={400}
responsiveOptions={{
heightCalculationMethod: "lowestElement",
widthCalculationMethod: "scrollWidth",
tolerance: 5,
autoResize: true,
maxHeight: 800,
minHeight: 200,
sizeWidth: true,
checkOrigin: false, // Set to true in production
}}
onResized={(dimensions) => {
console.log("New dimensions:", dimensions);
}}
onMessage={(message) => {
console.log("Message from iframe:", message);
}}
onInit={(iframe) => {
console.log("Iframe initialized:", iframe);
}}
/>
);
}
`$3
`jsx
import { ResponsiveIframe } from "react-responsive-iframe";
import { useRef } from "react";function ManualControlExample() {
const iframeRef = useRef();
const handleAddContent = () => {
// Send message to iframe to add content
iframeRef.current?.sendMessage({
type: "addContent",
data: "New content added!",
});
};
const handleForceResize = () => {
// Force iframe to recalculate its size
iframeRef.current?.resize();
};
return (
ref={iframeRef}
src="https://example.com"
width="100%"
height={300}
responsiveOptions={{
autoResize: true,
tolerance: 1,
}}
/>
);
}
`$3
`jsx
import { useIframeResizer } from "react-responsive-iframe";
import { useState } from "react";function DynamicContentExample() {
const [content, setContent] = useState("Initial content");
const { resize, isInitialized } = useIframeResizer({
heightCalculationMethod: "bodyScroll",
autoResize: true,
});
const addContent = () => {
setContent(
(prev) =>
prev +
"\n\nAdditional content added at " +
new Date().toLocaleTimeString()
);
// Force resize after content change
setTimeout(() => resize(), 100);
};
const removeContent = () => {
setContent("Minimal content");
// Force resize after content removal
setTimeout(() => resize(), 100);
};
return (
Dynamic Content Example
Status: {isInitialized ? "โ
Connected" : "โณ Connecting..."}
{content}
);
}
`$3
`jsx
import { ResponsiveIframe } from "react-responsive-iframe";function EventBasedExample() {
return (
Event-Based Resizing
Only resizes when content changes or window resizes (no intervals)
src="http://localhost:3001"
width="100%"
height={300}
responsiveOptions={{
heightCalculationMethod: "lowestElement",
autoResize: true, // Event-based only
tolerance: 1,
minHeight: 200,
maxHeight: 800,
}}
onResized={(dimensions) => {
console.log("โ
Iframe resized to:", dimensions);
}}
/>
);
}
`$3
Here's a complete example showing both parent and child components working together:
Parent App (main application):
`jsx
import React, { useRef } from "react";
import { ResponsiveIframe } from "react-responsive-iframe";function App() {
const iframeRef = useRef();
const handleResize = (dimensions) => {
console.log("๐ Iframe resized to:", dimensions);
};
const sendMessage = () => {
iframeRef.current?.sendMessage({
type: "updateContent",
data: "New content from parent!",
});
};
return (
๐ React Responsive Iframe Demo
ref={iframeRef}
src="http://localhost:3001"
width="100%"
height={400}
responsiveOptions={{
heightCalculationMethod: "bodyScroll",
autoResize: true,
tolerance: 1,
minHeight: 200,
maxHeight: 1000,
checkOrigin: false, // Set to true in production
}}
onResized={handleResize}
onMessage={(message) => {
console.log("๐จ Message from iframe:", message);
}}
onInit={(iframe) => {
console.log("โ
Iframe initialized");
}}
/>
);
}export default App;
`Child App (iframe content):
`jsx
import React, { useState, useEffect } from "react";
import { useIframeResizer } from "react-responsive-iframe";function IframeApp() {
const [content, setContent] = useState("Welcome to the iframe content!");
const [messageCount, setMessageCount] = useState(0);
const { sendMessage, resize, isInitialized } = useIframeResizer({
heightCalculationMethod: "bodyScroll",
autoResize: true,
minHeight: 200,
maxHeight: 800,
tolerance: 1,
onParentMessage: (message) => {
if (message.type === "updateContent") {
setContent(message.data);
setMessageCount((prev) => prev + 1);
}
},
});
const addContent = () => {
setContent(
(prev) =>
prev +
"\n\n๐ Additional content added at " +
new Date().toLocaleTimeString()
);
};
const sendResponse = () => {
sendMessage({
type: "response",
data:
Response #${messageCount + 1} from iframe,
timestamp: new Date().toISOString(),
});
}; return (
style={{
padding: 20,
fontFamily: "Arial, sans-serif",
backgroundColor: "#f9f9f9",
minHeight: "100vh",
}}
>
๐ฏ Iframe Content
style={{
background: "#fff",
padding: 15,
margin: "10px 0",
borderRadius: "8px",
border: "1px solid #ddd",
}}
>
Status:{" "}
{isInitialized ? "โ
Connected" : "โณ Connecting..."}
Messages received: {messageCount}
style={{
style={{
export default IframeApp;
`
| Method | Description | Use Case |
| --------------------- | ------------------------------------------ | ---------------------- |
| bodyScroll | Uses document.body.scrollHeight | Simple content |
| bodyOffset | Uses document.body.offsetHeight | Content with margins |
| documentElementScroll | Uses document.documentElement.scrollHeight | Full page content |
| documentElementOffset | Uses document.documentElement.offsetHeight | Full page with margins |
| max | Uses maximum of all methods | Complex layouts |
| min | Uses minimum of all methods | Conservative sizing |
| grow | Only increases height, never decreases | Growing content |
| lowestElement | Finds the lowest element on page | Dynamic content |
| Method | Description | Use Case |
| ----------- | ----------------------------------------- | --------------------- |
| scrollWidth | Uses document.documentElement.scrollWidth | Full content width |
| offsetWidth | Uses document.documentElement.offsetWidth | Visible content width |
| max | Uses maximum of both methods | Wide content |
| min | Uses minimum of both methods | Narrow content |
`jsx`
// For best performance
heightCalculationMethod: "bodyScroll", // Faster than lowestElement
autoResize: true, // Event-based only
tolerance: 1, // Small tolerance for accuracy
minHeight: 200, // Set constraints
maxHeight: 1000,
}}
/>
`jsx``
// Don't use for performance-sensitive apps
heightCalculationMethod: "lowestElement", // Expensive calculation
interval: 1000, // Continuous checking (not needed with event-based)
}}
/>
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
If you encounter any issues or have questions, please open an issue on our GitHub repository.
---
Made with โค๏ธ for the React community