jquery get height of iframe content when loaded
Asked Answered
P

11

94

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>
Presa answered 2/10, 2010 at 14:22 Comment(2)
Is the content of the iFrame coming from the same domain as the page it's in?Touraine
yes it is andrew, I want to use an iFrame because I use anchors in the help pagePresa
P
111

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';
}
Presa answered 3/10, 2010 at 21:4 Comment(8)
this solution works great as the above just gets the size from the iframes cocntent within the container while this gets the real sizeCapitalization
I believe the load event triggers on the same event loop so a setTimout of 1 millisecond will work just as wellKatlynkatmai
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.Drawshave
You may want the document height, not the body height. Using jQuery you can grab it with $(this.contentWindow.document).height().Avail
To older ie, iframe.contentDocument.body.offsetHeight will work. #2685193Novercal
I preferr scrollHeight instead of offsetHeight see this SO for detailsMacedonia
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.Hagiarchy
When I run this I'm getting Uncaught DOMException: Permission denied to access property "document" on cross-origin object 😕Zooid
T
54

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 );
Touraine answered 2/10, 2010 at 15:36 Comment(3)
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..Presa
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" />)Touraine
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.Touraine
C
26

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.

Canute answered 11/9, 2014 at 6:9 Comment(4)
works ok but for the width i have to do it like this or the contents gets cut $('iframe').width($('iframe').contents().width()+30);Monoploid
@AminGhaderi Works fine for me in firefox 40.0.3Deplete
@Deplete 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.Oriana
@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 flowDeplete
K
10

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)
Kwarteng answered 2/9, 2016 at 14:51 Comment(2)
Nice and simple! Unfortunately not work for cross-domain iframes :(Kauffman
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.Kwarteng
H
6

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);
}
Heteronomy answered 26/1, 2012 at 18:37 Comment(2)
This also won't work if you are displaying a PDF within the iframe.Sverdlovsk
Sorry but your example "inside frame" is clearly jQuery based.Viper
E
5

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>
Emmet answered 25/3, 2019 at 0:40 Comment(0)
A
4

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();
    });
Avril answered 15/2, 2018 at 20:23 Comment(0)
C
4

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: "Uncaught TypeError: a.indexOf is not a function" error when opening new foundation project

Cissie answered 14/5, 2018 at 19:34 Comment(0)
F
2

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`;
});
Fewer answered 4/6, 2020 at 22:57 Comment(0)
S
1

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
});
Salmonella answered 7/5, 2020 at 14:20 Comment(0)
G
0

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;
    }
    
Glossematics answered 2/10, 2021 at 13:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.