416

I need a solution for auto-adjusting the width and height of an iframe to barely fit its content. The point is that the width and height can be changed after the iframe has been loaded. I guess I need an event action to deal with the change in dimensions of the body contained in the iframe.

aleksandrbel
  • 1,422
  • 3
  • 20
  • 38
StoneHeart
  • 15,790
  • 32
  • 67
  • 84
  • Angular iFrame Auto-Height: https://gitlab.com/reduardo7/angular-iframe-auto-height – Eduardo Cuomo Oct 03 '16 at 14:53
  • The accepted answer does not work. Try https://stackoverflow.com/a/31513163/482382 – Steven Shaw Jul 05 '19 at 00:23
  • https://getbootstrap.com/docs/4.0/utilities/embed/ After a lot of research, it dawned on me, this is not a unique problem, I bet Bootstrap handles it. Lo and behold… – AZ Chad Jan 27 '22 at 12:52
  • if you control the iframe source, then you're in luck solutions suggested below may work or you can explore things like - https://github.com/davidjbradshaw/iframe-resizer in case you're use case has iframe source which you don't control, there's no solution for it, atleast i couldn't find it – akshay Aug 24 '22 at 12:56

35 Answers35

321
<script type="application/javascript">

function resizeIFrameToFitContent( iFrame ) {

    iFrame.width  = iFrame.contentWindow.document.body.scrollWidth;
    iFrame.height = iFrame.contentWindow.document.body.scrollHeight;
}

window.addEventListener('DOMContentLoaded', function(e) {

    var iFrame = document.getElementById( 'iFrame1' );
    resizeIFrameToFitContent( iFrame );

    // or, to resize all iframes:
    var iframes = document.querySelectorAll("iframe");
    for( var i = 0; i < iframes.length; i++) {
        resizeIFrameToFitContent( iframes[i] );
    }
} );

</script>

<iframe src="usagelogs/default.aspx" id="iFrame1"></iframe>
Cave Johnson
  • 6,499
  • 5
  • 38
  • 57
Ahmy
  • 5,420
  • 8
  • 39
  • 50
  • 3
    Not standards compliant, but by far the most easy way to do this. – Pim Jager May 04 '09 at 09:39
  • I don't know what do u mean with Not standards compliant? – Ahmy May 04 '09 at 09:42
  • 9
    @StoneHeart: yes, it's cross browser. The code is non-standard compliant because of contentWindow property, which isn't defined in DOM spec. In DOM spec exists property called contentDocument, but Internet Explorer 6 (and 7?) doesn't support it. The contentWindow property can be used instead and it's implemented in all common browsers (Gecko, Opera, Webkit, IE). – Rafael May 04 '09 at 10:28
  • BTW. the scrollHeight property - IIRC - also isn't standard compliant, but is also supported by all common browsers. You can use offsetHeight or other properties instead, but scrollHeight gives best results – Rafael May 04 '09 at 10:37
  • 31
    What's the use of if(document.getElementById) ? – Ally Aug 29 '12 at 10:43
  • 69
    Also don't forget it's not cross domain. Reason of which it's getting a kind of _Error: Permission denied to access property 'document'_ if the domain is different. A solution can be found [here](http://css-tricks.com/cross-domain-iframe-resizing/) – Pierre de LESPINAY Nov 12 '12 at 16:25
  • 1
    did not work for ff 16.01... firebug reports that contentWindow does not exist or it's undefined. – Tony Feb 12 '13 at 09:41
  • 3
    For IE9 , try `frame.style.height= (newheight) + "px"` and `frame.style.width= (newwidth) + "px";` – Amitd Mar 14 '13 at 15:55
  • 1
    Keep in mind a lot of content will not fully load for several minutes, or "never", so in some cases the onLoad will appear to never fire. This happens for any content that is "by design" to not respond quickly to certain requests, like the "polling" design Facebook uses for auto-updates. It happens with more content than you might think (learning this the hard way trying to use this design for a browser-based email client that display HTML email in an iFrame). – eselk Mar 26 '13 at 18:23
  • 2
    If you don't need to support older browsers, sending messages in between the windows is perhaps a cleaner solution: http://stackoverflow.com/questions/5606920/cross-domain-iframe-resizer/6940531#6940531 – Pavel Oct 31 '13 at 15:32
  • 1
    Why did you assign the variables `newheight` and `newwidth` inside of a conditional? When would `document.getElementById` return false, 0, undefined, or null? – teewuane Feb 11 '14 at 21:09
  • 15
    The conditional is not only useless but in the rare circumstance it's intended for is guaranteed to cause problems. Why are you checking to see if a method exists and then using the method outside of the check?? – J S Apr 22 '14 at 22:57
  • 1
    This sets the height correctly for me, but the width always stays at its original 100%. Both Chrome and Firefox. Anyone else experience this? – James Oct 20 '15 at 23:48
  • 1
    Why are there spaces before `.body.scrollHeight` and `.body.scrollWidth`? – Ben Dec 03 '15 at 19:48
  • How to set iFrame width for disabled JavaScript? If I set it inside of the iFrame element or via CSS your script doesn't resize anymore. – Ben Dec 03 '15 at 19:55
  • That only applies if the actual iFrame height is smaller than defined. – Ben Dec 03 '15 at 20:02
  • 6
    I think you meant `DOMContentLoaded`, since `DOMContentReady` doesn't seem to be a thing: https://developer.mozilla.org/en-US/search?q=domcontentready&topic=apps&topic=html&topic=css&topic=js&topic=api&topic=webdev – Max Heiber Sep 14 '16 at 20:40
  • 1
    @mheiber that is correct. I am really surprised that the code does not work with the typo, but has 204 updates - especially since this is a code-only answer – Adam Feb 22 '17 at 09:13
  • Inside the iframe if I have a
    with css "display: none" and change it by "display: block" it does not work. How to resize iframe when
    changes from "block to none" or "none to block"?
    – Popularfan Sep 06 '18 at 11:12
  • 1
    This answer does not work. Try https://stackoverflow.com/a/31513163/482382 – Steven Shaw Jul 05 '19 at 00:23
  • @StevenShaw: Thank you, mate, I had to cut through so much garbage until I found your link! – Sz. Aug 30 '19 at 00:22
  • This did not work for MS Edge, for me. I switched to the excellent iframe-resizer library: https://github.com/davidjbradshaw/iframe-resizer – stldoug Jun 30 '20 at 22:49
  • This doesn't account for margin that might be applied to the iframe's document. – Bouke Feb 23 '21 at 13:40
  • You're gonna want e.g. `...document.body.parentElement.scrollHeight` if you want to include all the page margins and padding. cc @Bouke – Jason C Jan 30 '22 at 19:41
  • 3
    Neither this solution or the one below work in any browser today. – WilliamK Jun 10 '22 at 21:06
  • 1
    In 2022, we may use iFrame.contentWindow.top.document.documentElement.scrollHeight instead. – Volotoka Nov 15 '22 at 00:53
74

one-liner solution for embeds: starts with a min-size and increases to content size. no need for script tags.

<iframe src="http://URL_HERE.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>
Guy
  • 5,370
  • 6
  • 25
  • 30
  • Run code snippet doesn't work with Safari 9.1.1 maybe include SO problem? – Elensar Jun 20 '16 at 12:04
  • 4
    It is not cross domain. Maybe the server needs to add some headers to the framed page? – Finesse Jul 21 '18 at 05:10
  • 2
    All answers here which mention `scrollHeight/scrollWidth` should be adjusted a bit to take body margins into account. Browsers apply default nonzero margins for documents' body element (and it's also applicable to content loaded into frames). The working solution I found is to add this: `parseInt(window.getComputedStyle(this.contentDocument.body).margin`. – Stan Nov 04 '19 at 21:50
  • @Stan there could be elements inside the document with a margin greater than that of the body, which is also not accounted for in your solution. – Bouke Feb 23 '21 at 13:41
  • @Stan Use `body.parentElement.scrollHeight` instead of `body.scrollHeight` (same for width) and it'll include document margins and stuff. It's the margins/padding of the top-level `html` element that end up excluded if you use `body`. – Jason C Jan 30 '22 at 19:43
  • 3
    Neither this solution or the one above work in any browser today. – WilliamK Jun 10 '22 at 21:06
53

Cross-browser jQuery plug-in.

Cross-bowser, cross domain library that uses mutationObserver to keep iFrame sized to the content and postMessage to communicate between iFrame and host page. Works with or without jQuery.

Community
  • 1
  • 1
FFish
  • 10,964
  • 34
  • 95
  • 136
37

All solutions given thus far only account for a once off resize. You mention you want to be able to resize the iFrame after the contents are modified. In order to do this, you need to execute a function inside the iFrame (once the contents are changed, you need to fire an event to say that the contents have changed).

I was stuck with this for a while, as code inside the iFrame seemed limited to the DOM inside the iFrame (and couldn't edit the iFrame), and code executed outside the iFrame was stuck with the DOM outside the iFrame (and couldn't pick up an event coming from inside the iFrame).

The solution came from discovering (via assistance from a colleague) that jQuery can be told what DOM to use. In this case, the DOM of the parent window.

As such, code such as this does what you need (when run inside the iFrame) :

<script type="text/javascript">
    jQuery(document).ready(function () {
        jQuery("#IDofControlFiringResizeEvent").click(function () {
            var frame = $('#IDofiframeInMainWindow', window.parent.document);
            var height = jQuery("#IDofContainerInsideiFrame").height();
            frame.height(height + 15);
        });
    });
</script>
Garnaph
  • 637
  • 7
  • 13
  • What would be the full code for this? I assume the script goes in the iframe html? – Andrew Hundt Dec 11 '13 at 22:01
  • This is the full code, and yes, it runs inside the iFrame's HTML. The "window.parent.document" part specifies that the jQuery selector should use the DOM of the parent document, and not the document you are in (which is inside the iFrame). – Garnaph Dec 14 '13 at 06:20
  • 16
    This works beautifully ***if the parent document and document in the iframe are both from the same domain***. If they aren't (or, in chrome, [if they're both local files](http://stackoverflow.com/questions/19462608/)), then browsers' "same origin" security policies kick in and it prevents the iframe contents from modifying the parent doc. – user56reinstatemonica8 Jan 14 '14 at 14:22
  • 1
    For anyone trying to make something like this work cross-domain, look into [**window.postMessage**](https://developer.mozilla.org/en-US/docs/Web/API/Window.postMessage) (IE8+) and be aware that you'll need custom scripts on both the host (parent) and the source (within iframe) documents. [jQuery postmessage plugin](http://benalman.com/projects/jquery-postmessage-plugin/) might help. Since you'll need scripts on the host and source, it might be easier to just have the host load the content by AJAX using JSON-P. – user56reinstatemonica8 Jan 14 '14 at 15:42
  • 4
    How to fire the event automatically instead of `jQuery("#IDofControlFiringResizeEvent").click(function ()`? – Ben Dec 03 '15 at 20:39
30

If the iframe content is from the same domain this should work great. It does require jQuery though.

$('#iframe_id').load(function () {
    $(this).height($(this).contents().height());
    $(this).width($(this).contents().width());
});

To have it resize dynamically you could do this:

<script language="javaScript">
<!--
function autoResize(){
    $('#themeframe').height($('#themeframe').contents().height());
}
//-->
</script>
<iframe id="themeframe" onLoad="autoResize();" marginheight="0" frameborder="0" src="URL"></iframe>

Then on the page that the iframe loads add this:

<script language="javaScript">
function resize()
{
    window.parent.autoResize();
}

$(window).on('resize', resize);
</script>
brenjt
  • 15,997
  • 13
  • 77
  • 118
16

Here is a cross-browser solution if you don't want to use jQuery:

/**
 * Resizes the given iFrame width so it fits its content
 * @param e The iframe to resize
 */
function resizeIframeWidth(e){
    // Set width of iframe according to its content
    if (e.Document && e.Document.body.scrollWidth) //ie5+ syntax
        e.width = e.contentWindow.document.body.scrollWidth;
    else if (e.contentDocument && e.contentDocument.body.scrollWidth) //ns6+ & opera syntax
        e.width = e.contentDocument.body.scrollWidth + 35;
    else (e.contentDocument && e.contentDocument.body.offsetWidth) //standards compliant syntax – ie8
        e.width = e.contentDocument.body.offsetWidth + 35;
}
Timo Ernst
  • 15,243
  • 23
  • 104
  • 165
  • 1
    That's strange. For me it calculates very weird width of iframe. contents width is 750 and it calculates it as 300. Do You have ideas why? – Rob Aug 02 '13 at 07:40
  • I played with this code (adding in height options). If I set the iFrame height at 100%, it restricts it to about 200px. If I set iFrame height at 600px, it sticks with that. @RobertJagoda did you get a solution to this? – iaindownie Aug 08 '13 at 09:58
9

After I have tried everything on the earth, this really works for me.

index.html

<style type="text/css">
html, body{
  width:100%;
  height:100%;
  overflow:hidden;
  margin:0px;   
}
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
function autoResize(iframe) {
    $(iframe).height($(iframe).contents().find('html').height());
}
</script>

<iframe src="http://iframe.domain.com" width="100%" height="100%" marginheight="0" frameborder="0" border="0" scrolling="auto" onload="autoResize(this);"></iframe>
Adrian P.
  • 5,060
  • 2
  • 46
  • 47
  • it says: Uncaught TypeError: $ is not a function at autoResize ((index):200) at HTMLIFrameElement.onload ((index):204) – Michael Rogers Sep 27 '17 at 22:10
  • 2
    @Michael Rogers There is a conflict with $ or you forget to include the jQuery.js file. Use a generic function https://stackoverflow.com/questions/6109847/jquery-is-not-a-function-error or replace $ with jQuery – Adrian P. Sep 28 '17 at 14:28
  • Look like I'll need an off-world solution because this didn't work. – user3035649 Jan 13 '22 at 19:13
8

I am using this code to autoadjust height of all iframes (with class autoHeight) when they loads on page. Tested and it works in IE, FF, Chrome, Safari and Opera.

function doIframe() {
    var $iframes = $("iframe.autoHeight"); 
    $iframes.each(function() {
        var iframe = this;
        $(iframe).load(function() {
            setHeight(iframe);
        });
    });
}

function setHeight(e) {
  e.height = e.contentWindow.document.body.scrollHeight + 35;
}

$(window).load(function() {
    doIframe();
});
petriq
  • 969
  • 1
  • 11
  • 24
  • 2
    What is this magic 35 you are adding? For which browser and OS did you measure it? – h2stein Nov 13 '12 at 10:09
  • Now I really do not know why I added 35 pixels. But I can certainly tell you that I tested it on FF, IE (7, 8, 9) & Chrome and I has worked just fine. – petriq Nov 29 '12 at 13:14
  • 3
    I think 35 is just the scroll-bar thickness – Sadegh Jan 24 '13 at 08:39
  • I had to tweak this a bit to get it to work - called setHeight(iframe); directly (removed the $(iframe).load() wrapper around it. – shacker Jul 03 '14 at 21:03
  • The magic 35 pixels added are to take into account the iframe padding. I'd add that the iframe should contain no padding the content of the iframeshould take care of this. – Filipe Melo Jan 21 '19 at 13:11
7

Context

I had to do this myself in a context of a web-extension. This web-extension injects some piece of UI into each page, and this UI lives inside an iframe. The content inside the iframe is dynamic, so I had to readjust the width and height of the iframe itself.

I use React but the concept applies to every library.

My solution (this assumes that you control both the page and the iframe)

Inside the iframe I changed body styles to have really big dimensions. This will allow the elements inside to lay out using all the necessary space. Making width and height 100% didn't work for me (I guess because the iframe has a default width = 300px and height = 150px)

/* something like this */
body {
  width: 99999px;
  height: 99999px;
}

Then I injected all the iframe UI inside a div and gave it some styles

#ui-root {
  display: 'inline-block';     
}

After rendering my app inside this #ui-root (in React I do this inside componentDidMount) I compute the dimensions of this div and sync them to the parent page using window.postMessage:

let elRect = el.getBoundingClientRect()
window.parent.postMessage({
  type: 'resize-iframe',
  payload: {
    width: elRect.width,
    height: elRect.height
  }
}, '*')

In the parent frame I do something like this:

window.addEventListener('message', (ev) => {
  if(ev.data.type && ev.data.type === 'resize-iframe') {
    iframe.style.width = ev.data.payload.width + 'px'
    iframe.style.height = ev.data.payload.height + 'px'
  }
}, false)
bboydflo
  • 907
  • 1
  • 15
  • 24
6

This is a solid proof solution

function resizer(id)
{

var doc=document.getElementById(id).contentWindow.document;
var body_ = doc.body, html_ = doc.documentElement;

var height = Math.max( body_.scrollHeight, body_.offsetHeight, html_.clientHeight, html_.scrollHeight, html_.offsetHeight );
var width  = Math.max( body_.scrollWidth, body_.offsetWidth, html_.clientWidth, html_.scrollWidth, html_.offsetWidth );

document.getElementById(id).style.height=height;
document.getElementById(id).style.width=width;

}

the html

<IFRAME SRC="blah.php" id="iframe1"  onLoad="resizer('iframe1');"></iframe>
Mas
  • 1,267
  • 1
  • 14
  • 13
  • 1
    First thank for that, it's a long time you post this. But the string value "px" is missing at the end of your last two instructions to make it work :) document.getElementById(id).style.height=height + "px"; document.getElementById(id).style.width=width + "px"; – Foxlab Feb 06 '23 at 16:40
4

If you can control both IFRAME content and parent window then you need the iFrame Resizer.

This library enables the automatic resizing of the height and width of both same and cross domain iFrames to fit their contained content. It provides a range of features to address the most common issues with using iFrames, these include:

  • Height and width resizing of the iFrame to content size.
  • Works with multiple and nested iFrames.
  • Domain authentication for cross domain iFrames.
  • Provides a range of page size calculation methods to support complex CSS layouts.
  • Detects changes to the DOM that can cause the page to resize using MutationObserver.
  • Detects events that can cause the page to resize (Window Resize, CSS Animation and Transition, Orientation Change and Mouse events).
  • Simplified messaging between iFrame and host page via postMessage.
  • Fixes in page links in iFrame and supports links between the iFrame and parent page.
  • Provides custom sizing and scrolling methods.
  • Exposes parent position and viewport size to the iFrame.
  • Works with ViewerJS to support PDF and ODF documents.
  • Fallback support down to IE8.
Sergey Ponomarev
  • 2,947
  • 1
  • 33
  • 43
3

I slightly modified Garnaph's great solution above. It seemed like his solution modified the iframe size based upon the size right before the event. For my situation (email submission via an iframe) I needed the iframe height to change right after submission. For example show validation errors or "thank you" message after submission.

I just eliminated the nested click() function and put it into my iframe html:

<script type="text/javascript">
    jQuery(document).ready(function () {
        var frame = $('#IDofiframeInMainWindow', window.parent.document);
        var height = jQuery("#IDofContainerInsideiFrame").height();
        frame.height(height + 15);
    });
</script>

Worked for me, but not sure about cross browser functionality.

udackds
  • 79
  • 1
  • 3
3

all can not work using above methods.

javascript:

function resizer(id) {
        var doc = document.getElementById(id).contentWindow.document;
        var body_ = doc.body, html_ = doc.documentElement;

        var height = Math.max(body_.scrollHeight, body_.offsetHeight, html_.clientHeight, html_.scrollHeight, html_.offsetHeight);
        var width = Math.max(body_.scrollWidth, body_.offsetWidth, html_.clientWidth, html_.scrollWidth, html_.offsetWidth);

        document.getElementById(id).style.height = height;
        document.getElementById(id).style.width = width;

    }

html:

<div style="background-color:#b6ff00;min-height:768px;line-height:inherit;height:inherit;margin:0px;padding:0px;overflow:visible" id="mainDiv"  >
         <input id="txtHeight"/>height     <input id="txtWidth"/>width     
        <iframe src="head.html" name="topFrame" scrolling="No" noresize="noresize" id="topFrame" title="topFrame" style="width:100%; height: 47px" frameborder="0"  ></iframe>
        <iframe src="left.aspx" name="leftFrame" scrolling="yes"   id="Iframe1" title="leftFrame" onload="resizer('Iframe1');" style="top:0px;left:0px;right:0px;bottom:0px;width: 30%; border:none;border-spacing:0px; justify-content:space-around;" ></iframe>
        <iframe src="index.aspx" name="mainFrame" id="Iframe2" title="mainFrame" scrolling="yes" marginheight="0" frameborder="0" style="width: 65%; height:100%; overflow:visible;overflow-x:visible;overflow-y:visible; "  onload="resizer('Iframe2');" ></iframe>
</div>

Env: IE 10, Windows 7 x64

Kalaschni
  • 2,301
  • 24
  • 37
Kevin
  • 31
  • 1
3

I figured out another solution after some experimenting. I originally tried the code marked as 'best answer' to this question and it didn't work. My guess is because my iframe in my program at the time was dynamically generated. Here is the code I used (it worked for me):

Javascript inside the iframe that is being loaded:

window.onload = function()
    {
        parent.document.getElementById('fileUploadIframe').style.height = document.body.clientHeight+5+'px';
        parent.document.getElementById('fileUploadIframe').style.width = document.body.clientWidth+18+'px';
    };

It is necessary to add 4 or more pixels to the height to remove scroll bars (some weird bug/effect of iframes). The width is even stranger, you are safe to add 18px to the width of the body. Also make sure that you have the css for the iframe body applied (below).

html, body {
   margin:0;
   padding:0;
   display:table;
}

iframe {
   border:0;
   padding:0;
   margin:0;
}

Here is the html for the iframe:

<iframe id="fileUploadIframe" src="php/upload/singleUpload.html"></iframe>

Here is all the code within my iframe:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>File Upload</title>
    <style type="text/css">
    html, body {
        margin:0;
        padding:0;
        display:table;
    }
    </style>
    <script type="text/javascript">
    window.onload = function()
    {
        parent.document.getElementById('fileUploadIframe').style.height = document.body.clientHeight+5+'px';
        parent.document.getElementById('fileUploadIframe').style.width = document.body.clientWidth+18+'px';
    };
    </script>
</head>
<body>
    This is a test.<br>
    testing
</body>
</html>

I have done testing in chrome and a little in firefox (in windows xp). I still have more testing to do, so please tell me how this works for you.

www139
  • 4,960
  • 3
  • 31
  • 56
  • thank you this works amazing in mobile browsers from what I've tested and that's where I was having problems with iframes being resized! – Mircea Sandu Jul 12 '15 at 19:48
  • Glad you like it :-) I have found iframe for the most part to be far more efficient and offer better browser support than Ajax. – www139 Jul 13 '15 at 02:13
  • 2
    THANK YOU!!! Mainly, because you are the only one who specified WHERE to put the code without assuming people know. This simple solution worked perfectly for me (Firefox, Chrome, Edge), for framing dynamic content on the same domain in my Wordpress site. I have a form-select which will output dynamic content of various lengths. The iFrame adjusts beautifully. I did have to tweak the .clientHeight+5+'px'; and clientWidth+18+'px'; to be more pixels. And I'm not sure why the display:table; in the CSS was needed so I commented it out for my purposes. Thanks again. – Heres2u Jan 30 '20 at 19:48
2

If you can live with a fixed aspect ratio and you would like a responsive iframe, this code will be useful to you. It's just CSS rules.

.iframe-container {
  overflow: hidden;
  /* Calculated from the aspect ration of the content (in case of 16:9 it is 9/16= 
  0.5625) */
  padding-top: 56.25%;
  position: relative;
}
.iframe-container iframe {
  border: 0;
  height: 100%;
  left: 0;
  position: absolute;
  top: 0;
  width: 100%;
}

The iframe must have a div as container.

<div class="iframe-container">
   <iframe src="http://example.org"></iframe>
</div>

The source code is based on this site and Ben Marshall has a good explanation.

negas
  • 841
  • 12
  • 10
2

I have been reading a lot of the answers here but nearly everyone gave some sort of cross-origin frame block.

Example error:

Uncaught DOMException: Blocked a frame with origin "null" from accessing a cross-origin frame.

The same for the answers in a related thread:

Make iframe automatically adjust height according to the contents without using scrollbar?

I do not want to use a third party library like iFrame Resizer or similar library either.

The answer from @bboydflo is close but I'm missing a complete example. https://stackoverflow.com/a/52204841/3850405

I'm using width="100%" for the iframe but the code can be modified to work with width as well.

This is how I solved setting a custom height for the iframe:

Embedded iframe:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="description"
          content="Web site" />
    <title>Test with embedded iframe</title>
</head>
<body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <iframe id="ifrm" src="https://localhost:44335/package/details?key=123" width="100%"></iframe>
    <script type="text/javascript">
        window.addEventListener('message', receiveMessage, false);

        function receiveMessage(evt) {
            console.log("Got message: " + JSON.stringify(evt.data) + " from origin: " + evt.origin);
            // Do we trust the sender of this message?
            if (evt.origin !== "https://localhost:44335") {
                return;
            }

            if (evt.data.type === "frame-resized") {
                document.getElementById("ifrm").style.height = evt.data.value + "px";
            }
        }
    </script>
</body>
</html>

iframe source, example from Create React App but only HTML and JS is used.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="description"
          content="Web site created using create-react-app" />
    <title>React App</title>
</head>
<body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <script type="text/javascript">
        //Don't run unless in an iframe
        if (self !== top) {
            var rootHeight;
            setInterval(function () {
                var rootElement = document.getElementById("root");
                if (rootElement) {
                    var currentRootHeight = rootElement.offsetHeight;
                    //Only send values if height has changed since last time
                    if (rootHeight !== currentRootHeight) {
                        //postMessage to set iframe height
                        window.parent.postMessage({ "type": "frame-resized", "value": currentRootHeight }, '*');
                        rootHeight = currentRootHeight;
                    }
                }
            }
                , 1000);
        }
    </script>
</body>
</html>

The code with setInterval can of course be modified but it works really well with dynamic content. setInterval only activates if the content is embedded in a iframe and postMessage only sends a message when height has changed.

You can read more about Window.postMessage() here but the description fits very good in what we want to achieve:

The window.postMessage() method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.

Normally, scripts on different pages are allowed to access each other if and only if the pages they originate from share the same protocol, port number, and host (also known as the "same-origin policy"). window.postMessage() provides a controlled mechanism to securely circumvent this restriction (if used properly).

https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

If you want 100% width and height for iframe I would do it like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="description"
          content="Web site" />
    <style>
        body {
            margin: 0; /* Reset default margin */
        }

        iframe {
            display: block; /* iframes are inline by default */
            background: #000;
            border: none; /* Reset default border */
            height: 100vh; /* Viewport-relative units */
            width: 100vw;
        }
    </style>
    <title>Test with embedded iframe</title>
</head>
<body>
    <iframe src="https://localhost:44335/package/details?key=123"></iframe>
</body>
</html>

Source:

https://stackoverflow.com/a/27853830/3850405

Ogglas
  • 62,132
  • 37
  • 328
  • 418
1

It is possible to make a "ghost-like" IFrame that acts like it was not there.

See http://codecopy.wordpress.com/2013/02/22/ghost-iframe-crossdomain-iframe-resize/

Basically you use the event system parent.postMessage(..) described in https://developer.mozilla.org/en-US/docs/DOM/window.postMessage

This works an all modern browsers!

Calciol
  • 429
  • 4
  • 5
1

Here are several methods:

<body style="margin:0px;padding:0px;overflow:hidden">
    <iframe src="http://www.example.com" frameborder="0" style="overflow:hidden;height:100%;width:100%" height="100%" width="100%"></iframe>
</body>

AND ANOTHER ALTERNATIVE

<body style="margin:0px;padding:0px;overflow:hidden">
    <iframe src="http://www.example.com" frameborder="0" style="overflow:hidden;overflow-x:hidden;overflow-y:hidden;height:100%;width:100%;position:absolute;top:0px;left:0px;right:0px;bottom:0px" height="100%" width="100%"></iframe>
</body>

TO HIDE SCROLLING WITH 2 ALTERNATIVES AS SHOWN ABOVE

<body style="margin:0px;padding:0px;overflow:hidden">
    <iframe src="http://www.example.com" frameborder="0" style="overflow:hidden;height:150%;width:150%" height="150%" width="150%"></iframe>
</body>

HACK WITH SECOND CODE

<body style="margin:0px;padding:0px;overflow:hidden">
    <iframe src="http://www.example.com" frameborder="0" style="overflow:hidden;overflow-x:hidden;overflow-y:hidden;height:150%;width:150%;position:absolute;top:0px;left:0px;right:0px;bottom:0px" height="150%" width="150%"></iframe>
</body>

To hide the scroll-bars of the iFrame, the parent is made "overflow:hidden" to hide scrollbars and the iFrame is made to go upto 150% width and height which forces the scroll-bars outside the page and since the body doesn't have scroll-bars one may not expect the iframe to be exceeding the bounds of the page. This hides the scrollbars of the iFrame with full width!

source: set iframe auto height

Community
  • 1
  • 1
T.Todua
  • 53,146
  • 19
  • 236
  • 237
  • 1
    The examples you gave are supposed to make iframe full content, not to autoresize the height of the iframe to fit all internal content. It doesn't reply the questions. – nickornotto Apr 16 '19 at 01:13
1

I found this resizer to work better:

function resizer(id)
{

    var doc = document.getElementById(id).contentWindow.document;
    var body_ = doc.body;
    var html_ = doc.documentElement;

    var height = Math.max( body_.scrollHeight, body_.offsetHeight, html_.clientHeight,     html_.scrollHeight, html_.offsetHeight );
    var width  = Math.max( body_.scrollWidth, body_.offsetWidth, html_.clientWidth, html_.scrollWidth, html_.offsetWidth );

    document.getElementById(id).height = height;
    document.getElementById(id).width = width;

}

Note the style object is removed.

ctrl-alt-delor
  • 7,506
  • 5
  • 40
  • 52
BabaRick
  • 27
  • 3
1

In case someone getting to here: I had a problem with the solutions when I removed divs from the iframe - the iframe didnt got shorter.

There is an Jquery plugin that does the job:

http://www.jqueryscript.net/layout/jQuery-Plugin-For-Auto-Resizing-iFrame-iFrame-Resizer.html

Sarah Sh
  • 451
  • 5
  • 15
1

In jQuery, this is the best option to me, that really help me!! I wait that help you!

iframe

<iframe src="" frameborder="0" id="iframe" width="100%"></iframe>

jQuery

<script>            
        var valueSize = $( "#iframe" ).offset();
        var totalsize = (valueSize.top * 2) + valueSize.left;

        $( "#iframe" ).height(totalsize);            

</script>
Kike Gamboa
  • 994
  • 7
  • 8
1

Clearly there are lots of scenarios, however, I had same domain for document and iframe and I was able to tack this on to the end of my iframe content:

var parentContainer = parent.document.querySelector("iframe[src*=\"" + window.location.pathname + "\"]");
parentContainer.style.height = document.body.scrollHeight + 50 + 'px';

This 'finds' the parent container and then sets the length adding on a fudge factor of 50 pixels to remove the scroll bar.

There is nothing there to 'observe' the document height changing, this I did not need for my use case. In my answer I do bring a means of referencing the parent container without using ids baked into the parent/iframe content.

Henry's Cat
  • 796
  • 12
  • 9
1
function resizeIFrameToFitContent(frame) {
if (frame == null) {
    return true;
}

var docEl = null;
var isFirefox = navigator.userAgent.search("Firefox") >= 0;

if (isFirefox && frame.contentDocument != null) {
    docEl = frame.contentDocument.documentElement;
} else if (frame.contentWindow != null) {
    docEl = frame.contentWindow.document.body;
}

if (docEl == null) {
    return;
}

var maxWidth = docEl.scrollWidth;
var maxHeight = (isFirefox ? (docEl.offsetHeight + 15) : (docEl.scrollHeight + 45));

frame.width = maxWidth;
frame.height = maxHeight;
frame.style.width = frame.width + "px";
frame.style.height = frame.height + "px";
if (maxHeight > 20) {
    frame.height = maxHeight;
    frame.style.height = frame.height + "px";
} else {
    frame.style.height = "100%";
}

if (maxWidth > 0) {
    frame.width = maxWidth;
    frame.style.width = frame.width + "px";
} else {
    frame.style.width = "100%";
}
}

ifram style:

.myIFrameStyle {
   float: left;
   clear: both;
   width: 100%;
   height: 200px;
   padding: 5px;
   margin: 0px;
   border: 1px solid gray;
   overflow: hidden;
}

iframe tag:

<iframe id="myIframe" src="" class="myIFrameStyle"> </iframe>

Script tag:

<script type="text/javascript">
   $(document).ready(function () {
      $('myIFrame').load(function () {
         resizeIFrameToFitContent(this);
      });
    });
</script>
x19
  • 8,277
  • 15
  • 68
  • 126
0

This is how I would do it (tested in FF/Chrome):

<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
function autoResize(iframe) {
    $(iframe).height($(iframe).contents().find('html').height());
}
</script>

<iframe src="page.html" width="100%" height="100" marginheight="0" frameborder="0" onload="autoResize(this);"></iframe>
Latheesan
  • 23,247
  • 32
  • 107
  • 201
0

I know the post is old, but I believe this is yet another way to do it. I just implemented on my code. Works perfectly both on page load and on page resize:

var videoHeight;
var videoWidth;
var iframeHeight;
var iframeWidth;

function resizeIframe(){
    videoHeight = $('.video-container').height();//iframe parent div's height
    videoWidth = $('.video-container').width();//iframe parent div's width

    iframeHeight = $('.youtubeFrames').height(videoHeight);//iframe's height
    iframeWidth = $('.youtubeFrames').width(videoWidth);//iframe's width
}
resizeIframe();


$(window).on('resize', function(){
    resizeIframe();
});
Gabriel Ferraz
  • 592
  • 6
  • 26
0

Javascript to be placed in header:

function resizeIframe(obj) {
        obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
      }

Here goes iframe html code:

<iframe class="spec_iframe" seamless="seamless" frameborder="0" scrolling="no" id="iframe" onload="javascript:resizeIframe(this);" src="somepage.php" style="height: 1726px;"></iframe>

Css stylesheet

>

.spec_iframe {
        width: 100%;
        overflow: hidden;
    }
Alin Razvan
  • 1,451
  • 13
  • 18
0

For angularjs directive attribute:

G.directive ( 'previewIframe', function () {
return {
    restrict : 'A',
    replace : true,
    scope : true,
    link : function ( scope, elem, attrs ) {
        elem.on ( 'load', function ( e ) {
            var currentH = this.contentWindow.document.body.scrollHeight;
            this.style.height = eval( currentH ) + ( (25 / 100)* eval( currentH ) ) + 'px';
        } );
    }
};
} );

Notice the percentage, i inserted it so that you can counter scaling usually done for iframe, text, ads etc, simply put 0 if no scaling is implementation

0

This is how I did it onload or when things change.

parent.jQuery("#frame").height(document.body.scrollHeight+50);
MrPHP
  • 152
  • 3
  • 12
0

If you are looking for a no jQuery cross-origin solution, you might want to look at my idea:

<main id="container"></main>
<script>
  fetch('https://example.com').then(response => {
    return response.text();
  }).then(data => {
    const iframeContainer = window.document.getElementById('container');
    const iframe = document.createElement('iframe');
    iframe.frameBorder = 'none';
    iframe.width = '100%';
    iframe.addEventListener("load", function() {
      iframe.height = iframe.contentWindow.document.body.scrollHeight;
    })
    const finalHtml = data;
    const blob = new Blob([finalHtml], {type: 'text/html'});
    iframe.src = window.URL.createObjectURL(blob);
    iframeContainer.appendChild(iframe);
  })
</script>
gruvw
  • 725
  • 8
  • 14
-1

Simplicity :

var iframe = $("#myframe");
$(iframe.get(0).contentWindow).on("resize", function(){
    iframe.width(iframe.get(0).contentWindow.document.body.scrollWidth);
    iframe.height(iframe.get(0).contentWindow.document.body.scrollHeight);
});
Séverin
  • 137
  • 1
  • 6
-1
<iframe src="hello.html" sandbox="allow-same-origin"
        onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';this.style.width=(this.contentWindow.document.body.scrollWidth+20)+'px';">
</iframe>
Chong Lip Phang
  • 8,755
  • 5
  • 65
  • 100
-1

If the content is just a very simple html, the simplest way is to remove the iframe with javascript

HTML code:

<div class="iframe">
    <iframe src="./mypage.html" frameborder="0" onload="removeIframe(this);"></iframe>
</div>

Javascript code:

function removeIframe(obj) {
    var iframeDocument = obj.contentDocument || obj.contentWindow.document;
    var mycontent = iframeDocument.getElementsByTagName("body")[0].innerHTML;
    obj.remove();
    document.getElementsByClassName("iframe")[0].innerHTML = mycontent;
}
Jakub Adamec
  • 953
  • 16
  • 22
Daniel Katz
  • 2,271
  • 3
  • 25
  • 27
  • 1
    This changes the parent document outline. If you want to have another document as a figure with a figcaption then this does not keep the document outline as succinct. Different use cases, but I wanted to move a code snippet to an iframe due to outline reasons. – Henry's Cat Apr 10 '19 at 10:00
-1

Use bootstrap's embed-responsive class, it's originally for youtube videos but you can adjust it's height.

If you can't use javascript I would suggest using bootstrap and playing around with embed-responsive-*** class of html. I was able to achieve the same with adding padding-bottom as percent to adjust it further accordingly.

<span class="iframe embed-responsive embed-responsive-16by9" style="display:block; padding-bottom: 10%;">
<iframe class="embed-responsive-item" width="100%" scrolling="no" src="example.com" frameBorder="0" ></iframe>
</span>
Amir Dora.
  • 2,831
  • 4
  • 40
  • 61
-1

The easiest way is to set the height for the iframe if you know what the height of the document is and if it's fixed.

Oybek Odilov
  • 185
  • 9
-7
<iframe src="..." style="border:none; width:100%; height: 100vh;"></iframe>
Foster
  • 136
  • 1
  • 8
  • 5
    Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes. – Dima Kozhevin Jul 27 '20 at 20:04