Answer: Use the contentWindow Property You can use the JavaScript contentWindow property to make an iFrame automatically adjust its height according to the contents inside it, so that no vertical scrollbar will appear.
Use the width, height, padding, and overflow properties to set the dimensions for the "wrap". Use the width, height, and border properties to set the dimensions for the “scaled-frame”. Add the zoom property to scale the content to 75%. Use the transform and transform-origin properties.
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();
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:
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);
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();">
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());"
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');
}
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With