jquery get height of iframe content when loaded

292,620

Solution 1

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

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

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

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

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);
}
Share:
292,620
FFish
Author by

FFish

Updated on July 08, 2022

Comments

  • FFish
    FFish almost 2 years

    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>
    
  • FFish
    FFish over 13 years
    Hi Andrew so far very good help here. contents() works great, but I still need to test it with a bandwidth throttler. Maybe you can use the innerHeight() property. I have a problem in FF (OSX) using your solution putting the height in the hash. FF seems to keep on loading the getDocumentHeight() function in an infinitive loop? Safari is fine..
  • Andrew
    Andrew over 13 years
    Interesting. I've added a check that prevents the setting of the hash if there's already a value there. You may need to tweak this if you are loading Help.php with a hash value (e.g. <iframe src="../Help.php#introduction" />)
  • Andrew
    Andrew over 13 years
    By the way, Assuming you can adjust for the difference in height, you probably needn't use the hash to communicate out of the iframe. If you do use the hash method, putting a sleep(5) in your Help.php should also be a good way of testing for any race conditions. If the iframe does somehow fire onLoad before onDOMReady, it should show up here.
  • rickyduck
    rickyduck over 12 years
    this solution works great as the above just gets the size from the iframes cocntent within the container while this gets the real size
  • Abhishek
    Abhishek over 11 years
    I believe the load event triggers on the same event loop so a setTimout of 1 millisecond will work just as well
  • JT...
    JT... about 11 years
    hhmmm Anyone know how to get the height of an iframe that's hidden at the time of loading the parent. This method brings back 0.
  • vpiTriumph
    vpiTriumph over 10 years
    You may want the document height, not the body height. Using jQuery you can grab it with $(this.contentWindow.document).height().
  • Jason Foglia
    Jason Foglia about 10 years
    This also won't work if you are displaying a PDF within the iframe.
  • Geomorillo
    Geomorillo over 9 years
    works ok but for the width i have to do it like this or the contents gets cut $('iframe').width($('iframe').contents().width()+30);
  • mixkat
    mixkat over 8 years
    @AminGhaderi Works fine for me in firefox 40.0.3
  • Amin Ghaderi
    Amin Ghaderi over 8 years
    @mixkat i do load a website in iframe via this solution and all solution in this topic but for me not work! i think this solutions do work for one page and do not work when we load complete a website into the iframe. my english is very bad , I hope you will understand.
  • mixkat
    mixkat over 8 years
    @AminGhaderi if I got this right you re expecting this to work for every page in your site but of course this won't work for all pages as it only runs once when you load the frame. So it'll work for the first page fine but then if you want it to work for longer pages you will have to do it again either by loading the frame again with the new page or by calling the contents.height at some other point in your flow
  • user1087079
    user1087079 about 8 years
    To older ie, iframe.contentDocument.body.offsetHeight will work. stackoverflow.com/questions/2684693/…
  • Anand Rockzz
    Anand Rockzz over 6 years
    I preferr scrollHeight instead of offsetHeight see this SO for details
  • TimoSolo
    TimoSolo about 6 years
    Nice and simple! Unfortunately not work for cross-domain iframes :(
  • cchamberlain
    cchamberlain about 6 years
    Yeah out of luck there. I'd leverage iframe-resizer library for that. Of course you need to be in control of both domains for it to work.
  • s427
    s427 over 5 years
    In my tests (both in Firefox and Chrome) the 3 lines about Opera & Safari needing a kick-start cause the $('iframe').load() to be triggered again, which executes the 3 lines about Opera and Safari again, which triggers the load(), etc, resulting in an infinite loop. Since it's a rather old answer, I'm not sure those 3 lines are still necessary today.
  • T-moty
    T-moty almost 5 years
    Sorry but your example "inside frame" is clearly jQuery based.
  • Brady Dowling
    Brady Dowling almost 3 years
    When I run this I'm getting Uncaught DOMException: Permission denied to access property "document" on cross-origin object 😕