The iframe is loaded from the same domain as the parent domain and therefore there are no cross-domain access issues.
An initial height of 0 can result in a sudden scrollbar ‘snap’ effect if the true height that is applied later is larger than the user’s viewport (even if you have the windows’ vertical scroll bar styled to always be visible).
Resizing feels a lot better if the initial height is downsized to the true height. In this example, I’ve used 1800px. Use a value that is greater than 95% of the typical content loaded into the iframe without getting ridiculous to cover edge cases.
When setting the initial value using either the
height attribute or inside a
style attribute, like the example above. It is important to then stay consistent with this choice when changing it later.
A lot of solutions to this use the
scrollHeight property and are done with it - but there are problems with this. As mentioned in the MDN documentation
it includes the element padding but not its margin.
There are three different properties you can use when calculating the height of an element:
The best solution I have come across is to use the iframes’
document element, check the value of all three, and take the largest value (credit to James Padolsey):
If you don’t care about documents in IE quirks mode you can drop the
You could use the .outerHeight() method
document element (
.outerHeight is not available at
A jQuery plugin for resizing iframes is available, though I have not tried it.
Here is the earlier code inside a function that then updates the height:
Detecting when an iframe has loaded natively is not simple. Here are some resources on this:
I have seen a number of occasions where the load event for the iframe fails to fire in IE 6 and IE 7. A fix for this is to manually execute
resizeClientIframe() after a defined period of time.
If the height of the iframe can change after loading, for example clicking on tabs changes displayed content, then you could modify the solution so that it is constantly checking:
However, this may not produce the result you were expecting (explained in Third-party iframes).
The content is served from a different sub-domain e.g.
clients.mysite.com . Change
document.domain to eliminate the sub-domain part:
The content is served from a different domain. You have access to the code on both domains.
For IE 6 and IE 7 support use easyXDM to communicate between the frames.
Firstly, let’s create the page to be loaded in an iframe (located at http://iframecontent.com) with the true height code:
Now let’s update this to send the true height to the parent document (located at http://parentdocument.com) using
The parent page loads the iframe and receives the height value from it.
event.origin is a security measure to prevent data coming from unauthorised senders. You can additionally supply the expected port number. Further details on postMessage.
Let’s modify this example to have the iframe content constantly changing the height and to regularly send the height to the parent document:
If we were to output the height value being passed to the parent document it would look something like this:
The value passed to the parent would only update when the content reached a larger value. This flaw is caused by our setting the height of the iframe in the parent document and the function checking the true height:
To show how mismatched browsers are when it comes to measuring document height here is a table of values in pixels returned by different browsers, for the resizing iframe example, where the height attribute has been hard coded to 1000px in the parent document.
|IE 10|| 1000||1000||1000||871||871||871|
The values in bold are the largest value for each browser. As the iframe content resizes the 1000px values only change when the content becomes larger while the smaller values correctly change.
*Firefox and IE 11 act differently in that some values will always have a minimum value of 1000px. So when the content is greater than 1000px it increases these values before reverting back to 1000px:
- Response 1: | 1000 | 405 | 1000 | 389 | 389 | 389 |
- Response 2: | 1422 | 1422 | 1000 | 1406 | 1406 | 1406 |
- Response 3: | 1000 | 480 | 1000 | 464 | 464 | 464 |
- Response 1: | 1000 | 414 | 1000 | 398 | 398 | 398 |
- Response 2: | 1389 | 1389 | 1000 | 1373 | 1373 | 1373 |
- Response 3: | 1000 | 913 | 1000 | 897 | 897 | 897 |
What we would hope for being returned is an output that updated when the content got smaller as well:
To fix this we need to send the current height set for the iframe in the parent document to the iframe, exclude any values that match this height (in the example above 1000) and then return the largest size still remaining.
Note: if you are do not have to support IE 8 and below I would probably re-write the code added from this point onwards.
Almost complete this leaves a slight snapping effect happening:
We need to alter the solution in the parent document to not update if the largest returned value is said between 20 pixels of the current height.
Mozilla have created an abstraction layer for postMessage that provides nicer syntax and a bunch of other features.
Iframes on smaller devices can act differently. Some can scroll; some not at all.
Iframes that take up a large amount of the viewport can be problematic. Having a visual cue like a frame border and space for a user to scroll both the iframe and the parent window can help.
There are some browser solutions to make accommodating iframe content much easier such as the
seamless attributes, covered in this post from bocoup, unfortunately browser support is marginal.