How to Create a Full-Screen iFrame with 100% Height (No More White Space)

Stop fighting CSS height issues. Get a perfect full-screen iFrame working in 10 minutes with this tested JavaScript solution.

I spent 4 hours fighting with CSS height properties trying to make an iframe fill the entire screen. White space everywhere, scrollbars in wrong places, and height calculations that made no sense.

Then I discovered the exact JavaScript approach that works every time.

What you'll build: A perfect full-screen iframe that adapts to any screen size Time needed: 10 minutes Difficulty: Beginner-friendly

This method eliminates the CSS guesswork and gives you pixel-perfect control over iframe dimensions.

Why I Built This

I was integrating a third-party dashboard into a client's admin panel. The iframe needed to fill the entire viewport - no navigation, no whitespace, just the embedded content.

My setup:

  • React app with iframe integration
  • Various screen sizes from mobile to 4K monitors
  • Cross-browser compatibility required
  • No access to modify the embedded content

What didn't work:

  • height: 100vh - left gaps with browser UI
  • height: 100% - didn't calculate parent heights properly
  • CSS-only solutions - broke on mobile browsers

The JavaScript Solution That Actually Works

The problem: CSS height calculations get messy with browser UI and nested containers.

My solution: Use JavaScript to calculate exact viewport dimensions and apply them directly.

Time this saves: No more CSS debugging sessions trying to eliminate mysterious white space.

Step 1: Create the Basic iFrame Structure

Start with clean HTML that JavaScript can target easily.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Full-Screen iFrame Demo</title>
    <style>
        /* Reset default margins/padding */
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        
        body {
            overflow: hidden; /* Prevent scrollbars on body */
        }
        
        #fullscreen-iframe {
            border: none;
            display: block;
        }
    </style>
</head>
<body>
    <iframe 
        id="fullscreen-iframe"
        src="https://example.com"
        frameborder="0"
        allowfullscreen>
    </iframe>
</body>
</html>

What this does: Sets up a clean container with no default spacing that could interfere with our calculations.

Expected output: An iframe that shows but isn't full-screen yet - you'll see it's not filling the viewport.

Personal tip: "The overflow: hidden on body is crucial - without it, you'll get unwanted scrollbars even with perfect dimensions."

Step 2: Add the JavaScript Height Calculator

This function handles the actual viewport calculation and iframe sizing.

function makeIframeFullScreen() {
    const iframe = document.getElementById('fullscreen-iframe');
    
    if (!iframe) {
        console.error('iFrame with ID "fullscreen-iframe" not found');
        return;
    }
    
    // Get exact viewport dimensions
    const viewportHeight = window.innerHeight;
    const viewportWidth = window.innerWidth;
    
    // Apply dimensions directly to iframe
    iframe.style.width = viewportWidth + 'px';
    iframe.style.height = viewportHeight + 'px';
    iframe.style.position = 'absolute';
    iframe.style.top = '0';
    iframe.style.left = '0';
    
    console.log(`iFrame sized to: ${viewportWidth}x${viewportHeight}`);
}

// Run on page load
document.addEventListener('DOMContentLoaded', makeIframeFullScreen);

// Handle window resize
window.addEventListener('resize', makeIframeFullScreen);

What this does: Measures the actual viewport and forces the iframe to match those exact pixel dimensions.

Expected output: An iframe that perfectly fills your browser window with no gaps or scrollbars.

Personal tip: "I use window.innerHeight instead of document.documentElement.clientHeight because innerHeight accounts for mobile browser UI changes."

Step 3: Handle Mobile Browser Quirks

Mobile browsers hide/show UI bars when scrolling, which changes the viewport height. Here's how to handle that smoothly:

function makeIframeFullScreen() {
    const iframe = document.getElementById('fullscreen-iframe');
    
    if (!iframe) {
        console.error('iFrame with ID "fullscreen-iframe" not found');
        return;
    }
    
    // Mobile-friendly viewport calculation
    let viewportHeight = window.innerHeight;
    let viewportWidth = window.innerWidth;
    
    // For iOS Safari - handle the address bar
    if (navigator.userAgent.includes('Safari') && !navigator.userAgent.includes('Chrome')) {
        // Use visual viewport if available (iOS 13+)
        if (window.visualViewport) {
            viewportHeight = window.visualViewport.height;
            viewportWidth = window.visualViewport.width;
        }
    }
    
    // Apply styles
    iframe.style.width = viewportWidth + 'px';
    iframe.style.height = viewportHeight + 'px';
    iframe.style.position = 'fixed'; // Changed from absolute
    iframe.style.top = '0';
    iframe.style.left = '0';
    iframe.style.zIndex = '9999';
    
    console.log(`Mobile-optimized iFrame: ${viewportWidth}x${viewportHeight}`);
}

// Enhanced event listeners for mobile
document.addEventListener('DOMContentLoaded', makeIframeFullScreen);
window.addEventListener('resize', makeIframeFullScreen);
window.addEventListener('orientationchange', () => {
    // Small delay to let the browser finish orientation change
    setTimeout(makeIframeFullScreen, 100);
});

// Handle visual viewport changes (iOS)
if (window.visualViewport) {
    window.visualViewport.addEventListener('resize', makeIframeFullScreen);
}

What this does: Adapts to mobile browser UI changes and device rotation smoothly.

Expected output: Perfect full-screen behavior on mobile devices, even when the address bar hides/shows.

Personal tip: "The 100ms timeout on orientation change is essential - without it, you'll get incorrect dimensions while the browser is still rotating."

Step 4: Add Error Handling and Loading States

Real-world applications need robust error handling. Here's the production-ready version:

class FullScreenIframe {
    constructor(iframeId, options = {}) {
        this.iframeId = iframeId;
        this.options = {
            showLoader: options.showLoader || true,
            loaderText: options.loaderText || 'Loading...',
            onLoad: options.onLoad || null,
            onError: options.onError || null,
            ...options
        };
        
        this.iframe = null;
        this.loader = null;
        this.init();
    }
    
    init() {
        this.iframe = document.getElementById(this.iframeId);
        
        if (!this.iframe) {
            console.error(`iFrame with ID "${this.iframeId}" not found`);
            return;
        }
        
        this.createLoader();
        this.setupEventListeners();
        this.makeFullScreen();
    }
    
    createLoader() {
        if (!this.options.showLoader) return;
        
        this.loader = document.createElement('div');
        this.loader.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: #f0f0f0;
            display: flex;
            align-items: center;
            justify-content: center;
            font-family: Arial, sans-serif;
            font-size: 18px;
            z-index: 10000;
        `;
        this.loader.textContent = this.options.loaderText;
        document.body.appendChild(this.loader);
    }
    
    makeFullScreen() {
        if (!this.iframe) return;
        
        let viewportHeight = window.innerHeight;
        let viewportWidth = window.innerWidth;
        
        // Handle iOS Safari visual viewport
        if (window.visualViewport) {
            viewportHeight = window.visualViewport.height;
            viewportWidth = window.visualViewport.width;
        }
        
        this.iframe.style.cssText = `
            width: ${viewportWidth}px;
            height: ${viewportHeight}px;
            position: fixed;
            top: 0;
            left: 0;
            border: none;
            z-index: 9999;
        `;
    }
    
    setupEventListeners() {
        // Resize handlers
        window.addEventListener('resize', () => this.makeFullScreen());
        window.addEventListener('orientationchange', () => {
            setTimeout(() => this.makeFullScreen(), 100);
        });
        
        if (window.visualViewport) {
            window.visualViewport.addEventListener('resize', () => this.makeFullScreen());
        }
        
        // iFrame load handlers
        this.iframe.addEventListener('load', () => {
            if (this.loader) {
                this.loader.remove();
                this.loader = null;
            }
            if (this.options.onLoad) this.options.onLoad();
        });
        
        this.iframe.addEventListener('error', () => {
            if (this.options.onError) this.options.onError();
            console.error('iFrame failed to load');
        });
    }
    
    destroy() {
        if (this.loader) this.loader.remove();
        // Remove event listeners if needed
    }
}

// Usage
document.addEventListener('DOMContentLoaded', () => {
    new FullScreenIframe('fullscreen-iframe', {
        showLoader: true,
        loaderText: 'Loading dashboard...',
        onLoad: () => console.log('Dashboard loaded successfully'),
        onError: () => console.error('Failed to load dashboard')
    });
});

What this does: Provides a professional class-based approach with loading states and error handling.

Expected output: A smooth loading experience with visual feedback and proper error handling.

Personal tip: "I always include the loader - users get confused when they see a blank screen, even for 2 seconds."

What You Just Built

A bulletproof full-screen iframe system that handles:

  • Exact viewport calculations
  • Mobile browser quirks
  • Device orientation changes
  • Loading states and error handling
  • Cross-browser compatibility

Key Takeaways (Save These)

  • Use window.innerHeight: More reliable than CSS viewport units for dynamic sizing
  • Handle visual viewport: Essential for iOS Safari's changing address bar
  • Add orientation delay: 100ms timeout prevents incorrect dimensions during device rotation

Your Next Steps

Pick one:

  • Beginner: Try embedding different content types (videos, dashboards, forms)
  • Intermediate: Add custom controls or communication between parent and iframe
  • Advanced: Implement iframe sandboxing and security policies

Tools I Actually Use

  • Chrome DevTools: Device simulation for testing mobile behavior
  • Visual Viewport API: Modern way to handle mobile browser UI changes
  • MDN Documentation: Visual Viewport API reference