jquery get height of iframe content when loaded

JqueryIframeHeightOnload

Jquery Problem Overview


I have a Help page, help.php that I am loading inside an iframe in main.php How can I get the height of this page once it has loaded in the iframe?

I am asking this because I can't style the height of to iframe to 100% or auto. That's why I think I need to use javascript.. I am using jQuery

CSS:

body {
    margin: 0;
    padding: 0;
}
.container {
    width: 900px;
    height: 100%;
    margin: 0 auto;
    background: silver;
}
.help-div {
    display: none;
    width: 850px;
    height: 100%;
    position: absolute;
    top: 100px;
    background: orange;
}
#help-frame {
    width: 100%;
    height: auto;
    margin:0;
    padding:0;
}

JS:

$(document).ready(function () {
    $("a.open-help").click(function () {
        $(".help-div").show();
        return false;
    })
})

HTML:

<div class='container'>
    <!-- -->
    <div class='help-div'>
        <p>This is a div with an iframe loading the help page</p>
        <iframe id="help-frame" src="../help.php" width="100%" height="100%" frameborder="1"></iframe>
    </div>	<a class="open-help" href="#">open Help in iFrame</a>

    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
    <p>hello world</p>
</div>

Jquery Solutions


Solution 1 - Jquery

ok I finally found a good solution:

$('iframe').load(function() {
    this.style.height =
    this.contentWindow.document.body.offsetHeight + 'px';
});

Because some browsers (older Safari and Opera) report onload completed before CSS renders you need to set a micro Timeout and blank out and reassign the iframe's src.

$('iframe').load(function() {
    setTimeout(iResize, 50);
    // Safari and Opera need a kick-start.
    var iSource = document.getElementById('your-iframe-id').src;
    document.getElementById('your-iframe-id').src = '';
    document.getElementById('your-iframe-id').src = iSource;
});
function iResize() {
    document.getElementById('your-iframe-id').style.height = 
    document.getElementById('your-iframe-id').contentWindow.document.body.offsetHeight + 'px';
}

Solution 2 - Jquery

The less complicated answer is to use .contents() to get at the iframe. Interestingly, though, it returns a different value from what I get using the code in my original answer, due to the padding on the body, I believe.

$('iframe').contents().height() + 'is the height'

This is how I've done it for cross-domain communication, so I'm afraid it's maybe unnecessarily complicated. First, I would put jQuery inside the iFrame's document; this will consume more memory, but it shouldn't increase load time as the script only needs to be loaded once.

Use the iFrame's jQuery to measure the height of your iframe's body as early as possible (onDOMReady) and then set the URL hash to that height. And in the parent document, add an onload event to the iFrame tag that will look at the location of the iframe and extract the value you need. Because onDOMReady will always occur before the document's load event, you can be fairly certain the value will get communicated correctly without a race condition complicating things.

In other words:

...in Help.php:

var getDocumentHeight = function() {
    if (location.hash === '') { // EDIT: this should prevent the retriggering of onDOMReady
        location.hash = $('body').height(); 
        // at this point the document address will be something like help.php#1552
    }
};
$(getDocumentHeight);

...and in the parent document:

var getIFrameHeight = function() {
    var iFrame = $('iframe')[0]; // this will return the DOM element
    var strHash = iFrame.contentDocument.location.hash;
    alert(strHash); // will return something like '#1552'
};
$('iframe').bind('load', getIFrameHeight );

Solution 3 - Jquery

I found the following to work on Chrome, Firefox and IE11:

$('iframe').load(function () {
    $('iframe').height($('iframe').contents().height());
});

When the Iframes content is done loading the event will fire and it will set the IFrames height to that of its content. This will only work for pages within the same domain as that of the IFrame.

Solution 4 - Jquery

The code to do this without jQuery is trivial nowadays:

const frame = document.querySelector('iframe')
function syncHeight() {
  this.style.height = `${this.contentWindow.document.body.offsetHeight}px`
}
frame.addEventListener('load', syncHeight)

To unhook the event:

frame.removeEventListener('load', syncHeight)

Solution 5 - Jquery

You don't need jquery inside the iframe to do this, but I use it cause the code is so much simpler...

Put this in the document inside your iframe.

$(document).ready(function() {
  parent.set_size(this.body.offsetHeight + 5 + "px");  
});

added five above to eliminate scrollbar on small windows, it's never perfect on size.

And this inside your parent document.

function set_size(ht)
{
$("#iframeId").css('height',ht);
}

Solution 6 - Jquery

this is the correct answer that worked for me

$(document).ready(function () {
        function resizeIframe() {
            if ($('iframe').contents().find('html').height() > 100) {
                $('iframe').height(($('iframe').contents().find('html').height()) + 'px')
            } else {
                setTimeout(function (e) {
                    resizeIframe();
                }, 50);
            }
        }
        resizeIframe();
    });

Solution 7 - Jquery

simple one-liner starts with a default min-height and increases to contents size.

<iframe src="http://url.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>

Solution 8 - Jquery

Accepted answer's $('iframe').load will now produce a.indexOf is not a function error. Can be updated to:

$('iframe').on('load', function() {
  // ...
});

Few others similar to .load deprecated since jQuery 1.8: https://stackoverflow.com/questions/38871753/uncaught-typeerror-a-indexof-is-not-a-function-error-when-opening-new-foundat

Solution 9 - Jquery

This is my ES6 friendly no-jquery take

document.querySelector('iframe').addEventListener('load', function() {
    const iframeBody = this.contentWindow.document.body;
    const height = Math.max(iframeBody.scrollHeight, iframeBody.offsetHeight);
    this.style.height = `${height}px`;
});

Solution 10 - Jquery

This's a jQuery free solution that can work with SPA inside the iframe

document.getElementById('iframe-id').addEventListener('load', function () {
  let that = this;
  setTimeout(function () {
    that.style.height = that.contentWindow.document.body.offsetHeight + 'px';
  }, 2000) // if you're having SPA framework (angularjs for example) inside the iframe, some delay is needed for the content to populate
});

Solution 11 - Jquery

Here is my solution, using pure JS for finding the total height of iframe content. NOTE:

  1. Call this function after the iframe is loaded.

  2. The iframe content must be in the same domain as the host page.

     function getIframeBodyTotalHeight() {
     var frm = document.getElementById("appframe");
     var frm_body = frm.contentWindow.document.body;
    
     var body_height = parseInt(frm_body.offsetHeight);
     var body_margin_top = parseInt(window.getComputedStyle(frm_body).getPropertyValue('margin-top').replace("px",""));
     var body_margin_bottom = parseInt(window.getComputedStyle(frm_body).getPropertyValue('margin-bottom').replace("px",""));
     var body_padding_top = parseInt(window.getComputedStyle(frm_body).getPropertyValue('padding-top').replace("px", ""));
     var body_padding_bottom = parseInt(window.getComputedStyle(frm_body).getPropertyValue('padding-bottom').replace("px", ""));
    
     var result = body_height + body_margin_top + body_margin_bottom + body_padding_top + body_padding_bottom;
     return result;
    }
    

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFFishView Question on Stackoverflow
Solution 1 - JqueryFFishView Answer on Stackoverflow
Solution 2 - JqueryAndrewView Answer on Stackoverflow
Solution 3 - JqueryJack Zach TibblesView Answer on Stackoverflow
Solution 4 - JquerycchamberlainView Answer on Stackoverflow
Solution 5 - JqueryRkaneKnightView Answer on Stackoverflow
Solution 6 - JqueryJavier GordoView Answer on Stackoverflow
Solution 7 - JqueryPixelomoView Answer on Stackoverflow
Solution 8 - JqueryRyan J. StoutView Answer on Stackoverflow
Solution 9 - JqueryCésar RiveraView Answer on Stackoverflow
Solution 10 - JqueryEnvilView Answer on Stackoverflow
Solution 11 - JqueryJonathan ApplebaumView Answer on Stackoverflow