225
votes

I am loading an aspx web page in an iframe. The content in the Iframe can be of more height than the iframe's height. The iframe should not have scroll bars.

I have a wrapper div tag inside the iframe which basically is all the content. I wrote some jQuery to make the resize happen :

$("#TB_window", window.parent.document).height($("body").height() + 50);

where TB_window is the div in which the Iframe is contained.

body - the body tag of the aspx in the iframe.

This script is attached to the iframe content. I am getting the TB_window element from the parent page. While this works fine on Chrome, but the TB_window collapses in Firefox. I am really confused/lost on why that happens.

22
that .aspx iframe page is from the same domain name ?AlexC
can you check $("body").height() has a value in firefox?Michael L Watson
yes..the iframe is in the same domain as the container pagekarry
@MichaelLWatson It looks like firebug watch window has the value as 0 for the body height...Chrome does have a value thoughkarry
Angular iFrame Auto-Height example: gitlab.com/reduardo7/angular-iframe-auto-heightEduardo Cuomo

22 Answers

220
votes

You can retrieve the height of the IFRAME's content by using: contentWindow.document.body.scrollHeight

After the IFRAME is loaded, you can then change the height by doing the following:

<script type="text/javascript">
  function iframeLoaded() {
      var iFrameID = document.getElementById('idIframe');
      if(iFrameID) {
            // here you can make the height, I delete it first, then I make it again
            iFrameID.height = "";
            iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
      }   
  }
</script>   

Then, on the IFRAME tag, you hook up the handler like this:

<iframe id="idIframe" onload="iframeLoaded()" ...

I had a situation a while ago where I additionally needed to call iframeLoaded from the IFRAME itself after a form-submission occurred within. You can accomplish that by doing the following within the IFRAME's content scripts:

parent.iframeLoaded();
120
votes

A slightly improved answer to Aristos...

<script type="text/javascript">
  function resizeIframe(iframe) {
    iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
  }
</script>  

Then declare in your iframe as follows:

<iframe onload="resizeIframe(this)" ...

There are two minor improvements:

  1. You don't need to get the element via document.getElementById - as you already have it in the onload callback.
  2. There's no need to set the iframe.height = "" if you're going to reassign it in the very next statement. Doing so actually incurs an overhead as you're dealing with a DOM element.

Edit: If the content in the frame is always changing then call:

parent.resizeIframe(this.frameElement); 

from within the iframe after the update. Works for same origin.

Or to auto detect:

  // on resize
  this.container = this.frameElement.contentWindow.document.body;

  this.watch = () => {
    cancelAnimationFrame(this.watcher);

    if (this.lastScrollHeight !== container.scrollHeight) {
      parent.resizeIframeToContentSize(this.frameElement);  
    }
    this.lastScrollHeight = container.scrollHeight;
    this.watcher = requestAnimationFrame(this.watch);
  };
  this.watcher = window.requestAnimationFrame(this.watch);
62
votes

I found that the accepted answer didn't suffice, since X-FRAME-OPTIONS: Allow-From isn't supported in safari or chrome. Went with a different approach instead, found in a presentation given by Ben Vinegar from Disqus. The idea is to add an event listener to the parent window, and then inside the iframe, use window.postMessage to send an event to the parent telling it to do something (resize the iframe).

So in the parent document, add an event listener:

window.addEventListener('message', function(e) {
  var $iframe = jQuery("#myIframe");
  var eventName = e.data[0];
  var data = e.data[1];
  switch(eventName) {
    case 'setHeight':
      $iframe.height(data);
      break;
  }
}, false);

And inside the iframe, write a function to post the message:

function resize() {
  var height = document.getElementsByTagName("html")[0].scrollHeight;
  window.parent.postMessage(["setHeight", height], "*"); 
}

Finally, inside the iframe, add an onLoad to the body tag to fire the resize function:

<body onLoad="resize();">
14
votes

Add this to the iframe, this worked for me:

onload="this.height=this.contentWindow.document.body.scrollHeight;"

And if you use jQuery try this code:

onload="$(this).height($(this.contentWindow.document.body).find(\'div\').first().height());"
5
votes

There are four different properties you can look at to get the height of the content in an iFrame.

document.documentElement.scrollHeight
document.documentElement.offsetHeight
document.body.scrollHeight
document.body.offsetHeight

Sadly they can all give different answers and these are inconsistant between browsers. If you set the body margin to 0 then the document.body.offsetHeight gives the best answer. To get the correct value try this function; which is taken from the iframe-resizer library that also looks after keeping the iFrame the correct size when the content changes,or the browser is resized.

function getIFrameHeight(){
    function getComputedBodyStyle(prop) {
        function getPixelValue(value) {
            var PIXEL = /^\d+(px)?$/i;

            if (PIXEL.test(value)) {
                return parseInt(value,base);
            }

            var 
                style = el.style.left,
                runtimeStyle = el.runtimeStyle.left;

            el.runtimeStyle.left = el.currentStyle.left;
            el.style.left = value || 0;
            value = el.style.pixelLeft;
            el.style.left = style;
            el.runtimeStyle.left = runtimeStyle;

            return value;
        }

        var 
            el = document.body,
            retVal = 0;

        if (document.defaultView && document.defaultView.getComputedStyle) {
            retVal =  document.defaultView.getComputedStyle(el, null)[prop];
        } else {//IE8 & below
            retVal =  getPixelValue(el.currentStyle[prop]);
        } 

        return parseInt(retVal,10);
    }

    return document.body.offsetHeight +
        getComputedBodyStyle('marginTop') +
        getComputedBodyStyle('marginBottom');
}
3
votes

you could also add a repeating requestAnimationFrame to your resizeIframe (e.g. from @BlueFish's answer) which would always be called before the browser paints the layout and you could update the height of the iframe when its content have changed their heights. e.g. input forms, lazy loaded content etc.

<script type="text/javascript">
  function resizeIframe(iframe) {
    iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
    window.requestAnimationFrame(() => resizeIframe(iframe));
  }
</script>  

<iframe onload="resizeIframe(this)" ...

your callback should be fast enough to have no big impact on your overall performance

3
votes

Other answers were not working for me so i did some changes. Hope this will help

$('#iframe').on("load", function() {
    var iframe = $(window.top.document).find("#iframe");
    iframe.height(iframe[0].ownerDocument.body.scrollHeight+'px' );
});
2
votes

Just in case this helps anyone. I was pulling my hair out trying to get this to work, then I noticed that the iframe had a class entry with height:100%. When I removed this, everything worked as expected. So, please check for any css conflicts.

2
votes

I am using jQuery and the code below working for me,

var iframe = $(window.top.document).find("#iframe_id_here");
iframe.height(iframe.contents().height()+'px' );
1
votes

You can refer related question here - How to make width and height of iframe same as its parent div?

To set dynamic height -

  1. We need to communicate with cross domain iFrames and parent
  2. Then we can send scroll height/content height of iframe to parent window

And codes - https://gist.github.com/mohandere/a2e67971858ee2c3999d62e3843889a8

1
votes

Rather than using javscript/jquery the easiest way I found is:

<iframe style="min-height:98vh" src="http://yourdomain.com" width="100%"></iframe>

Here 1vh = 1% of Browser window height. So the theoretical value of height to be set is 100vh but practically 98vh did the magic.

0
votes

I found the answer from Troy didn't work. This is the same code reworked for ajax:

$.ajax({                                      
    url: 'data.php',    
    dataType: 'json',                             

    success: function(data)
    {
        // Put the data onto the page

        // Resize the iframe
        var iframe = $(window.top.document).find("#iframe");
        iframe.height( iframe[0].contentDocument.body.scrollHeight+'px' );
    }
});
0
votes

To add to the chunk of window that seems to cut off at the bottom, especially when you don't have scrolling I used:

function resizeIframe(iframe) {
    var addHeight = 20; //or whatever size is being cut off
    iframe.height = iframe.contentWindow.document.body.scrollHeight + addHeight + "px";
  }
0
votes

This one is useful when you require a solution with no jquery. In that case you should try adding a container and set a padding to it in percentages

HTML example code:

<div class="iframecontainer">
    <iframe scrolling="no" src="..." class="iframeclass"width="999px" height="618px"></iframe>
</div>

CSS example code:

.iframeclass{
    position: absolute;
    top: 0;
    width: 100%;
}

.iframecontainer{
    position: relative;
    width: 100%;
    height: auto;
    padding-top: 61%;
}
0
votes

The simple solution is to measure the width and height of the content area, and then use those measurements to calculate the bottom padding percentage.

In this case, the measurements are 1680 x 720 px, so the padding on the bottom is 720 / 1680 = 0.43 * 100, which comes out to 43%.

.canvas-container {    
    position: relative;
    padding-bottom: 43%; // (720 ÷ 1680 = 0.4286 = 43%)
    height: 0;
    overflow: hidden;   
}

.canvas-container iframe {    
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;   
}
0
votes

A slightly improved answer to BlueFish...

function resizeIframe(iframe) {
    var padding = 50;
    if (iframe.contentWindow.document.body.scrollHeight < (window.innerHeight - padding))
        iframe.height = iframe.contentWindow.document.body.scrollHeight + "px";
    else
        iframe.height = (window.innerHeight - padding) + "px";
}

This takes in consideration the height of the windows screen(browser, phone) which is good for responsive design and iframes that have huge height. Padding represents the padding you want above and below the iframe in the case it goes trough whole screen.

0
votes
jQuery('.home_vidio_img1 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery(this).replaceWith(video);
});

jQuery('.home_vidio_img2 img').click(function(){
    video = <iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>;
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});

jQuery('.home_vidio_img3 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});

jQuery('.home_vidio_img4 img').click(function(){
    video = '<iframe src="'+ jQuery(this).attr('data-video') +'"></iframe>';
    jQuery('.home_vidio_img1 img').replaceWith(video);
    jQuery('.home_vidio_img1 iframe').replaceWith(video);
});
0
votes

Sample using PHP htmlspecialchars() + check if height exists and is > 0:

$my_html_markup = ''; // Insert here HTML markup with CSS, JS... '<html><head></head><body>...</body></html>'
$iframe = '<iframe onload="if(this.contentWindow.document.body.scrollHeight) {this.height = this.contentWindow.document.body.scrollHeight;}" width="100%" src="javascript: \''. htmlspecialchars($my_html_markup) . '\'"></iframe>';
0
votes

All other answers are correct but what if the iframe has some dynamic content like a map that loads later and dynamically changes your iframe scroll height. This is how I achieved it.

var iFrameID = document.getElementById('idIframe');

intval =  setInterval(function(){
if(iFrameID.scrollHeight == iFrameID.contentWindow.document.body.scrollHeight){
     clearInterval(intval);
}else{
   iFrameID.height = iFrameID.contentWindow.document.body.scrollHeight + "px";
  }
},500)

I simply wrap the code inside setInterval which matches the iframe scroll height with iframe content scroll height then clear the interval.

0
votes

in my project there is one requirement that we have make dynamic screen like Alignment of Dashboard while loading, it should display on an entire page and should get adjust dynamically, if user is maximizing or resizing the browser’s window. For this I have created url and used iframe to open one of the dynamic report which is written in cognos BI.In jsp we have to embed BI report. I have used iframe to embed this report in jsp. following code is working in my case.

<iframe src= ${cognosUrl} onload="this.style.height=(this.contentDocument.body.scrollHeight+30) +'px';" scrolling="no" style="width: 100%; min-height: 900px; border: none; overflow: hidden; height: 30px;"></iframe>
-1
votes
$(document).height() // - $('body').offset().top

and / or

$(window).height()

See Stack Overflow question How to get the height of a body element.

Try this to find the height of the body in jQuery:

if $("body").height()

It doesn't have a value if Firebug. Perhaps that's the problem.

-1
votes

just make iframe container position:absolute and iframe will automatically change its height according to its content

<style>
   .iframe-container {
       display: block;
       position: absolute;
       /*change position as you need*/
       bottom: 0;
       left: 0;
       right: 0;
       top: 0;
   }
   iframe {
       margin: 0;
       padding: 0;
       border: 0;
       width: 100%;
       background-color: #fff;
   }
 </style>
 <div class="iframe-container">
     <iframe src="http://iframesourcepage"></iframe>
 </div>