[javascript] Adjust width and height of iframe to fit with content in it

I need a solution for auto-adjusting the width and height of an iframe to barely fit its content. The point is that the width and height can be changed after the iframe has been loaded. I guess I need an event action to deal with the change in dimensions of the body contained in the iframe.

This question is related to javascript html iframe adjustment

The answer is


I slightly modified Garnaph's great solution above. It seemed like his solution modified the iframe size based upon the size right before the event. For my situation (email submission via an iframe) I needed the iframe height to change right after submission. For example show validation errors or "thank you" message after submission.

I just eliminated the nested click() function and put it into my iframe html:

<script type="text/javascript">
    jQuery(document).ready(function () {
        var frame = $('#IDofiframeInMainWindow', window.parent.document);
        var height = jQuery("#IDofContainerInsideiFrame").height();
        frame.height(height + 15);
    });
</script>

Worked for me, but not sure about cross browser functionality.


I found this resizer to work better:

function resizer(id)
{

    var doc = document.getElementById(id).contentWindow.document;
    var body_ = doc.body;
    var html_ = doc.documentElement;

    var height = Math.max( body_.scrollHeight, body_.offsetHeight, html_.clientHeight,     html_.scrollHeight, html_.offsetHeight );
    var width  = Math.max( body_.scrollWidth, body_.offsetWidth, html_.clientWidth, html_.scrollWidth, html_.offsetWidth );

    document.getElementById(id).height = height;
    document.getElementById(id).width = width;

}

Note the style object is removed.


If you can live with a fixed aspect ratio and you would like a responsive iframe, this code will be useful to you. It's just CSS rules.

.iframe-container {
  overflow: hidden;
  /* Calculated from the aspect ration of the content (in case of 16:9 it is 9/16= 
  0.5625) */
  padding-top: 56.25%;
  position: relative;
}
.iframe-container iframe {
  border: 0;
  height: 100%;
  left: 0;
  position: absolute;
  top: 0;
  width: 100%;
}

The iframe must have a div as container.

<div class="iframe-container">
   <iframe src="http://example.org"></iframe>
</div>

The source code is based on this site and Ben Marshall has a good explanation.


If the iframe content is from the same domain this should work great. It does require jQuery though.

$('#iframe_id').load(function () {
    $(this).height($(this).contents().height());
    $(this).width($(this).contents().width());
});

To have it resize dynamically you could do this:

<script language="javaScript">
<!--
function autoResize(){
    $('#themeframe').height($('#themeframe').contents().height());
}
//-->
</script>
<iframe id="themeframe" onLoad="autoResize();" marginheight="0" frameborder="0" src="URL"></iframe>

Then on the page that the iframe loads add this:

<script language="javaScript">
function resize()
{
    window.parent.autoResize();
}

$(window).on('resize', resize);
</script>

This is a solid proof solution

function resizer(id)
{

var doc=document.getElementById(id).contentWindow.document;
var body_ = doc.body, html_ = doc.documentElement;

var height = Math.max( body_.scrollHeight, body_.offsetHeight, html_.clientHeight, html_.scrollHeight, html_.offsetHeight );
var width  = Math.max( body_.scrollWidth, body_.offsetWidth, html_.clientWidth, html_.scrollWidth, html_.offsetWidth );

document.getElementById(id).style.height=height;
document.getElementById(id).style.width=width;

}

the html

<IFRAME SRC="blah.php" id="iframe1"  onLoad="resizer('iframe1');"></iframe>

Context

I had to do this myself in a context of a web-extension. This web-extension injects some piece of UI into each page, and this UI lives inside an iframe. The content inside the iframe is dynamic, so I had to readjust the width and height of the iframe itself.

I use React but the concept applies to every library.

My solution (this assumes that you control both the page and the iframe)

Inside the iframe I changed body styles to have really big dimensions. This will allow the elements inside to lay out using all the necessary space. Making width and height 100% didn't work for me (I guess because the iframe has a default width = 300px and height = 150px)

/* something like this */
body {
  width: 99999px;
  height: 99999px;
}

Then I injected all the iframe UI inside a div and gave it some styles

#ui-root {
  display: 'inline-block';     
}

After rendering my app inside this #ui-root (in React I do this inside componentDidMount) I compute the dimensions of this div like and sync them to the parent page using window.postMessage:

let elRect = el.getBoundingClientRect()
window.parent.postMessage({
  type: 'resize-iframe',
  payload: {
    width: elRect.width,
    height: elRect.height
  }
}, '*')

In the parent frame I do something like this:

window.addEventListener('message', (ev) => {
  if(ev.data.type && ev.data.type === 'resize-iframe') {
    iframe.style.width = ev.data.payload.width + 'px'
    iframe.style.height = ev.data.payload.height + 'px'
  }
}, false)

This is how I did it onload or when things change.

parent.jQuery("#frame").height(document.body.scrollHeight+50);

Javascript to be placed in header:

function resizeIframe(obj) {
        obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
      }

Here goes iframe html code:

<iframe class="spec_iframe" seamless="seamless" frameborder="0" scrolling="no" id="iframe" onload="javascript:resizeIframe(this);" src="somepage.php" style="height: 1726px;"></iframe>

Css stylesheet

>

.spec_iframe {
        width: 100%;
        overflow: hidden;
    }

If the content is just a very simple html, the simplest way is to remove the iframe with javascript

HTML code:

<div class="iframe">
    <iframe src="./mypage.html" frameborder="0" onload="removeIframe(this);"></iframe>
</div>

Javascript code:

function removeIframe(obj) {
    var iframeDocument = obj.contentDocument || obj.contentWindow.document;
    var mycontent = iframeDocument.getElementsByTagName("body")[0].innerHTML;
    obj.remove();
    document.getElementsByClassName("iframe")[0].innerHTML = mycontent;
}

Clearly there are lots of scenarios, however, I had same domain for document and iframe and I was able to tack this on to the end of my iframe content:

var parentContainer = parent.document.querySelector("iframe[src*=\"" + window.location.pathname + "\"]");
parentContainer.style.height = document.body.scrollHeight + 50 + 'px';

This 'finds' the parent container and then sets the length adding on a fudge factor of 50 pixels to remove the scroll bar.

There is nothing there to 'observe' the document height changing, this I did not need for my use case. In my answer I do bring a means of referencing the parent container without using ids baked into the parent/iframe content.


Here are several methods:

<body style="margin:0px;padding:0px;overflow:hidden">
    <iframe src="http://www.example.com" frameborder="0" style="overflow:hidden;height:100%;width:100%" height="100%" width="100%"></iframe>
</body>

AND ANOTHER ALTERNATIVE

<body style="margin:0px;padding:0px;overflow:hidden">
    <iframe src="http://www.example.com" frameborder="0" style="overflow:hidden;overflow-x:hidden;overflow-y:hidden;height:100%;width:100%;position:absolute;top:0px;left:0px;right:0px;bottom:0px" height="100%" width="100%"></iframe>
</body>

TO HIDE SCROLLING WITH 2 ALTERNATIVES AS SHOWN ABOVE

<body style="margin:0px;padding:0px;overflow:hidden">
    <iframe src="http://www.example.com" frameborder="0" style="overflow:hidden;height:150%;width:150%" height="150%" width="150%"></iframe>
</body>

HACK WITH SECOND CODE

<body style="margin:0px;padding:0px;overflow:hidden">
    <iframe src="http://www.example.com" frameborder="0" style="overflow:hidden;overflow-x:hidden;overflow-y:hidden;height:150%;width:150%;position:absolute;top:0px;left:0px;right:0px;bottom:0px" height="150%" width="150%"></iframe>
</body>

To hide the scroll-bars of the iFrame, the parent is made "overflow:hidden" to hide scrollbars and the iFrame is made to go upto 150% width and height which forces the scroll-bars outside the page and since the body doesn't have scroll-bars one may not expect the iframe to be exceeding the bounds of the page. This hides the scrollbars of the iFrame with full width!

source: set iframe auto height


In jQuery, this is the best option to me, that really help me!! I wait that help you!

iframe

<iframe src="" frameborder="0" id="iframe" width="100%"></iframe>

jQuery

<script>            
        var valueSize = $( "#iframe" ).offset();
        var totalsize = (valueSize.top * 2) + valueSize.left;

        $( "#iframe" ).height(totalsize);            

</script>

one-liner solution for embeds: starts with a min-size and increases to content size. no need for script tags.

_x000D_
_x000D_
<iframe src="http://URL_HERE.html" onload='javascript:(function(o){o.style.height=o.contentWindow.document.body.scrollHeight+"px";}(this));' style="height:200px;width:100%;border:none;overflow:hidden;"></iframe>
_x000D_
_x000D_
_x000D_


all can not work using above methods.

javascript:

function resizer(id) {
        var doc = document.getElementById(id).contentWindow.document;
        var body_ = doc.body, html_ = doc.documentElement;

        var height = Math.max(body_.scrollHeight, body_.offsetHeight, html_.clientHeight, html_.scrollHeight, html_.offsetHeight);
        var width = Math.max(body_.scrollWidth, body_.offsetWidth, html_.clientWidth, html_.scrollWidth, html_.offsetWidth);

        document.getElementById(id).style.height = height;
        document.getElementById(id).style.width = width;

    }

html:

<div style="background-color:#b6ff00;min-height:768px;line-height:inherit;height:inherit;margin:0px;padding:0px;overflow:visible" id="mainDiv"  >
         <input id="txtHeight"/>height     <input id="txtWidth"/>width     
        <iframe src="head.html" name="topFrame" scrolling="No" noresize="noresize" id="topFrame" title="topFrame" style="width:100%; height: 47px" frameborder="0"  ></iframe>
        <iframe src="left.aspx" name="leftFrame" scrolling="yes"   id="Iframe1" title="leftFrame" onload="resizer('Iframe1');" style="top:0px;left:0px;right:0px;bottom:0px;width: 30%; border:none;border-spacing:0px; justify-content:space-around;" ></iframe>
        <iframe src="index.aspx" name="mainFrame" id="Iframe2" title="mainFrame" scrolling="yes" marginheight="0" frameborder="0" style="width: 65%; height:100%; overflow:visible;overflow-x:visible;overflow-y:visible; "  onload="resizer('Iframe2');" ></iframe>
</div>

Env: IE 10, Windows 7 x64


I figured out another solution after some experimenting. I originally tried the code marked as 'best answer' to this question and it didn't work. My guess is because my iframe in my program at the time was dynamically generated. Here is the code I used (it worked for me):

Javascript inside the iframe that is being loaded:

window.onload = function()
    {
        parent.document.getElementById('fileUploadIframe').style.height = document.body.clientHeight+5+'px';
        parent.document.getElementById('fileUploadIframe').style.width = document.body.clientWidth+18+'px';
    };

It is necessary to add 4 or more pixels to the height to remove scroll bars (some weird bug/effect of iframes). The width is even stranger, you are safe to add 18px to the width of the body. Also make sure that you have the css for the iframe body applied (below).

html, body {
   margin:0;
   padding:0;
   display:table;
}

iframe {
   border:0;
   padding:0;
   margin:0;
}

Here is the html for the iframe:

<iframe id="fileUploadIframe" src="php/upload/singleUpload.html"></iframe>

Here is all the code within my iframe:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>File Upload</title>
    <style type="text/css">
    html, body {
        margin:0;
        padding:0;
        display:table;
    }
    </style>
    <script type="text/javascript">
    window.onload = function()
    {
        parent.document.getElementById('fileUploadIframe').style.height = document.body.clientHeight+5+'px';
        parent.document.getElementById('fileUploadIframe').style.width = document.body.clientWidth+18+'px';
    };
    </script>
</head>
<body>
    This is a test.<br>
    testing
</body>
</html>

I have done testing in chrome and a little in firefox (in windows xp). I still have more testing to do, so please tell me how this works for you.


Cross-browser jQuery plug-in.

Cross-bowser, cross domain library that uses mutationObserver to keep iFrame sized to the content and postMessage to communicate between iFrame and host page. Works with or without jQuery.


Here is a cross-browser solution if you don't want to use jQuery:

/**
 * Resizes the given iFrame width so it fits its content
 * @param e The iframe to resize
 */
function resizeIframeWidth(e){
    // Set width of iframe according to its content
    if (e.Document && e.Document.body.scrollWidth) //ie5+ syntax
        e.width = e.contentWindow.document.body.scrollWidth;
    else if (e.contentDocument && e.contentDocument.body.scrollWidth) //ns6+ & opera syntax
        e.width = e.contentDocument.body.scrollWidth + 35;
    else (e.contentDocument && e.contentDocument.body.offsetWidth) //standards compliant syntax – ie8
        e.width = e.contentDocument.body.offsetWidth + 35;
}

<iframe src="hello.html" sandbox="allow-same-origin"
        onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';this.style.width=(this.contentWindow.document.body.scrollWidth+20)+'px';">
</iframe>

Simplicity :

var iframe = $("#myframe");
$(iframe.get(0).contentWindow).on("resize", function(){
    iframe.width(iframe.get(0).contentWindow.document.body.scrollWidth);
    iframe.height(iframe.get(0).contentWindow.document.body.scrollHeight);
});

All solutions given thus far only account for a once off resize. You mention you want to be able to resize the iFrame after the contents are modified. In order to do this, you need to execute a function inside the iFrame (once the contents are changed, you need to fire an event to say that the contents have changed).

I was stuck with this for a while, as code inside the iFrame seemed limited to the DOM inside the iFrame (and couldn't edit the iFrame), and code executed outside the iFrame was stuck with the DOM outside the iFrame (and couldn't pick up an event coming from inside the iFrame).

The solution came from discovering (via assistance from a colleague) that jQuery can be told what DOM to use. In this case, the DOM of the parent window.

As such, code such as this does what you need (when run inside the iFrame) :

<script type="text/javascript">
    jQuery(document).ready(function () {
        jQuery("#IDofControlFiringResizeEvent").click(function () {
            var frame = $('#IDofiframeInMainWindow', window.parent.document);
            var height = jQuery("#IDofContainerInsideiFrame").height();
            frame.height(height + 15);
        });
    });
</script>

For angularjs directive attribute:

G.directive ( 'previewIframe', function () {
return {
    restrict : 'A',
    replace : true,
    scope : true,
    link : function ( scope, elem, attrs ) {
        elem.on ( 'load', function ( e ) {
            var currentH = this.contentWindow.document.body.scrollHeight;
            this.style.height = eval( currentH ) + ( (25 / 100)* eval( currentH ) ) + 'px';
        } );
    }
};
} );

Notice the percentage, i inserted it so that you can counter scaling usually done for iframe, text, ads etc, simply put 0 if no scaling is implementation


I am using this code to autoadjust height of all iframes (with class autoHeight) when they loads on page. Tested and it works in IE, FF, Chrome, Safari and Opera.

function doIframe() {
    var $iframes = $("iframe.autoHeight"); 
    $iframes.each(function() {
        var iframe = this;
        $(iframe).load(function() {
            setHeight(iframe);
        });
    });
}

function setHeight(e) {
  e.height = e.contentWindow.document.body.scrollHeight + 35;
}

$(window).load(function() {
    doIframe();
});

After I have tried everything on the earth, this really works for me.

index.html

<style type="text/css">
html, body{
  width:100%;
  height:100%;
  overflow:hidden;
  margin:0px;   
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
function autoResize(iframe) {
    $(iframe).height($(iframe).contents().find('html').height());
}
</script>

<iframe src="http://iframe.domain.com" width="100%" height="100%" marginheight="0" frameborder="0" border="0" scrolling="auto" onload="autoResize(this);"></iframe>

function resizeIFrameToFitContent(frame) {
if (frame == null) {
    return true;
}

var docEl = null;
var isFirefox = navigator.userAgent.search("Firefox") >= 0;

if (isFirefox && frame.contentDocument != null) {
    docEl = frame.contentDocument.documentElement;
} else if (frame.contentWindow != null) {
    docEl = frame.contentWindow.document.body;
}

if (docEl == null) {
    return;
}

var maxWidth = docEl.scrollWidth;
var maxHeight = (isFirefox ? (docEl.offsetHeight + 15) : (docEl.scrollHeight + 45));

frame.width = maxWidth;
frame.height = maxHeight;
frame.style.width = frame.width + "px";
frame.style.height = frame.height + "px";
if (maxHeight > 20) {
    frame.height = maxHeight;
    frame.style.height = frame.height + "px";
} else {
    frame.style.height = "100%";
}

if (maxWidth > 0) {
    frame.width = maxWidth;
    frame.style.width = frame.width + "px";
} else {
    frame.style.width = "100%";
}
}

ifram style:

.myIFrameStyle {
   float: left;
   clear: both;
   width: 100%;
   height: 200px;
   padding: 5px;
   margin: 0px;
   border: 1px solid gray;
   overflow: hidden;
}

iframe tag:

<iframe id="myIframe" src="" class="myIFrameStyle"> </iframe>

Script tag:

<script type="text/javascript">
   $(document).ready(function () {
      $('myIFrame').load(function () {
         resizeIFrameToFitContent(this);
      });
    });
</script>

I know the post is old, but I believe this is yet another way to do it. I just implemented on my code. Works perfectly both on page load and on page resize:

var videoHeight;
var videoWidth;
var iframeHeight;
var iframeWidth;

function resizeIframe(){
    videoHeight = $('.video-container').height();//iframe parent div's height
    videoWidth = $('.video-container').width();//iframe parent div's width

    iframeHeight = $('.youtubeFrames').height(videoHeight);//iframe's height
    iframeWidth = $('.youtubeFrames').width(videoWidth);//iframe's width
}
resizeIframe();


$(window).on('resize', function(){
    resizeIframe();
});

In case someone getting to here: I had a problem with the solutions when I removed divs from the iframe - the iframe didnt got shorter.

There is an Jquery plugin that does the job:

http://www.jqueryscript.net/layout/jQuery-Plugin-For-Auto-Resizing-iFrame-iFrame-Resizer.html


This is how I would do it (tested in FF/Chrome):

<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
function autoResize(iframe) {
    $(iframe).height($(iframe).contents().find('html').height());
}
</script>

<iframe src="page.html" width="100%" height="100" marginheight="0" frameborder="0" onload="autoResize(this);"></iframe>

If you can control both IFRAME content and parent window then you need the iFrame Resizer.

This library enables the automatic resizing of the height and width of both same and cross domain iFrames to fit their contained content. It provides a range of features to address the most common issues with using iFrames, these include:

  • Height and width resizing of the iFrame to content size.
  • Works with multiple and nested iFrames.
  • Domain authentication for cross domain iFrames.
  • Provides a range of page size calculation methods to support complex CSS layouts.
  • Detects changes to the DOM that can cause the page to resize using MutationObserver.
  • Detects events that can cause the page to resize (Window Resize, CSS Animation and Transition, Orientation Change and Mouse events).
  • Simplified messaging between iFrame and host page via postMessage.
  • Fixes in page links in iFrame and supports links between the iFrame and parent page.
  • Provides custom sizing and scrolling methods.
  • Exposes parent position and viewport size to the iFrame.
  • Works with ViewerJS to support PDF and ODF documents.
  • Fallback support down to IE8.

It is possible to make a "ghost-like" IFrame that acts like it was not there.

See http://codecopy.wordpress.com/2013/02/22/ghost-iframe-crossdomain-iframe-resize/

Basically you use the event system parent.postMessage(..) described in https://developer.mozilla.org/en-US/docs/DOM/window.postMessage

This works an all modern browsers!


<iframe src="..." style="border:none; width:100%; height: 100vh;"></iframe>

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to iframe

Getting all files in directory with ajax YouTube Autoplay not working Inserting the iframe into react component How to disable auto-play for local video in iframe iframe refuses to display iFrame onload JavaScript event YouTube iframe embed - full screen Change New Google Recaptcha (v2) Width load iframe in bootstrap modal Responsive iframe using Bootstrap

Examples related to adjustment

Adjust width and height of iframe to fit with content in it