ChatGPT解决这个技术问题 Extra ChatGPT

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

This question already has answers here: Adjust width and height of iframe to fit with content in it (35 answers) Closed 6 years ago.

For example:

<iframe name="Stack" src="http://stackoverflow.com/" width="740"
        frameborder="0" scrolling="no" id="iframe"> ...
</iframe>

I want it to be able to adjust its height according to the contents inside it, without using scroll.

This can be done via CSS there is a concept in css called media queries where content is resized according to the screen size
"Angular…" i.e., Javascript required? In other words, one cannot do this on cross-site iframes (due to cross-site scripting restrictions), is that right? As @clankill3r is suggesting, this demonstrates the need for a pure CSS solution to this problem!

T
Trevor

Add this to your <head> section:

<script>
  function resizeIframe(obj) {
    obj.style.height = obj.contentWindow.document.documentElement.scrollHeight + 'px';
  }
</script>

And change your iframe to this:

<iframe src="..." frameborder="0" scrolling="no" onload="resizeIframe(this)" />

As found on sitepoint discussion.


This will not work if the iframe contains content from another domain because of the Same Origin Policy, there is another Question on SO with some cross domain solutions stackoverflow.com/questions/5589756/…
The solutions seems not to work if the content of the iframe has a change of height by js (e.g a slider)
should be onload="resizeIframe(this);" :)
Their are a few other issues you need to consider, content changing in the iframe, the browser being resized, the iframe not being full loaded when you first check it and cross domain. I put together a little library, because I couldn't find a solution that covered every issue. github.com/davidjbradshaw/iframe-resizer
Might be worth changing scrolling to auto in case the iframe's contents increase in height after being loaded.
D
David Bradshaw

You can use this library, which both initially sizes your iframe correctly and also keeps it at the right size by detecting whenever the size of the iframe's content changes (either via regular checking in a setInterval or via MutationObserver) and resizing it.

https://github.com/davidjbradshaw/iframe-resizer

Their is also a React version.

https://github.com/davidjbradshaw/iframe-resizer-react

This works with both cross and same domain iframes.


This is by far the most robust solution.
note: when using for cross domain, requires you to be able to inject a js file into the iframe... Doesn't seem like a viable option when you don't control the iframe source.
A major bug in this library is that it can't handle vh.
@RickardElimää would be happy to take a PR to fix vh.
@MattWeiler in that case you can still just monkey patch the JS file into the other apps, you don't need to change any of their code and including that file won't have any negative effect on your old apps
C
Chong Lip Phang

Here is a compact version:

<iframe src="hello.html" sandbox="allow-same-origin"
        onload="this.style.height=(this.contentWindow.document.body.scrollHeight+20)+'px';">
</iframe>

I haven't tried this with other browsers, but I needed to add 10px with Chrome or else a vertical scrollbar showed up. I did this.style.height=(this.contentDocument.body.scrollHeight + 15) + 'px'; just to make sure it looks ok.
This solution adding a "max-height:400px !important; " to fix the maximum height is the perfect for my case.
it should be onload="this.style.height = this.contentWindow.document.body.scrollHeight + 'px';"
not working.. getting Blocked a frame with origin "{url}" from accessing a cross-origin frame.
works fine for me.
r
rybo111

The suggestion by hjpotter92 does not work in safari! I have made a small adjustment to the script so it now works in Safari as well.

Only change made is resetting height to 0 on every load in order to enable some browsers to decrease height.

Add this to <head> tag:

<script type="text/javascript">
  function resizeIframe(obj){
     obj.style.height = 0;
     obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
  }
</script>

And add the following onload attribute to your iframe, like so

<iframe onload='resizeIframe(this)'></iframe>

This also does not work if the iframe contents come from srcdoc attribute. The height will be set wrong.
Setting height to zero first is not only for IE.
Thanks, this probably should have been a comment/suggestion to hjpotter's post mind...
You don't need those encapsulating {}'s
obj.style.height = 0; is very important row, that cause scrollHeight recalculating (otherwise, your contentWindow height will only increase).
J
Jimadine

The hjpotter92 answer works well enough in certain cases, but I found the iframe content often got bottom-clipped in Firefox & IE, while fine in Chrome.

The following works well for me and fixes the clipping problem. The code was found at http://www.dyn-web.com/tutorials/iframes/height/. I have made a slight modification to take the onload attribute out of the HTML. Place the following code after the <iframe> HTML and before the closing </body> tag:

<script type="text/javascript">
function getDocHeight(doc) {
    doc = doc || document;
    // stackoverflow.com/questions/1145850/
    var body = doc.body, html = doc.documentElement;
    var height = Math.max( body.scrollHeight, body.offsetHeight, 
        html.clientHeight, html.scrollHeight, html.offsetHeight );
    return height;
}

function setIframeHeight(id) {
    var ifrm = document.getElementById(id);
    var doc = ifrm.contentDocument? ifrm.contentDocument: 
        ifrm.contentWindow.document;
    ifrm.style.visibility = 'hidden';
    ifrm.style.height = "10px"; // reset to minimal height ...
    // IE opt. for bing/msn needs a bit added or scrollbar appears
    ifrm.style.height = getDocHeight( doc ) + 4 + "px";
    ifrm.style.visibility = 'visible';
}

document.getElementById('ifrm').onload = function() { // Adjust the Id accordingly
    setIframeHeight(this.id);
}
</script>

Your iframe HTML:

<iframe id="ifrm" src="some-iframe-content.html"></iframe>

Note if you prefer to include the Javascript in the <head> of the document then you can revert to using an inline onload attribute in the iframe HTML, as in the dyn-web web page.


This is the only one that worked for me. Thank you so much!
Not working now in 2021.
r
rybo111

Avoid inline JavaScript; you can use a class:

<iframe src="..." frameborder="0" scrolling="auto" class="iframe-full-height"></iframe>

And reference it with jQuery:

$('.iframe-full-height').on('load', function(){
    this.style.height=this.contentDocument.body.scrollHeight +'px';
});

N
Nathalia Xavier

jQuery's .contents() method method allows us to search through the immediate children of the element in the DOM tree.

jQuery:

$('iframe').height( $('iframe').contents().outerHeight() );

Remember that the body of the page inner the iframe must have its height

CSS:

body {
  height: auto;
  overflow: auto
}

Add a demo to your answer to give it more value.
This worked for me but only when removing 'body' to make it contents()
same problem as before, doesn't work cross origin
jQuery('iframe').height(jQuery('iframe').contents().find('body').height()); worked for me when the iframe had loaded
L
Lucky

Try this for IE11

<iframe name="Stack" src="http://stackoverflow.com/" style='height: 100%; width: 100%;' frameborder="0" scrolling="no" id="iframe">...</iframe>

Why are you writing for one browser? Many people, with many operating systems, and many browsers will view your site.
Works! (on Chrome, Firefox, Safari, IE)
u
user2992220

This works for me (also with multiple iframes on one page):

$('iframe').load(function(){$(this).height($(this).contents().outerHeight());});

c
ctrl-alt-delor

This works for me (mostly).

Put this at the bottom of your page.

<script type="application/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js">
</script>

<script type="application/javascript" src="/script/jquery.browser.js">
</script>

<script type="application/javascript" src="/script/jquery-iframe-auto-height.js">
</script>

<script type="application/javascript"> 
  jQuery('iframe').iframeAutoHeight();
  $(window).load(
      function() {
          jQuery('iframe').iframeAutoHeight();  
      }
  );

  // for when content is not html e.g. a PDF
  function setIframeHeight() {
      $('.iframe_fullHeight').each(
          function (i, item) {
              item.height = $(document).height();
          }
      );
  };

  $(document).ready( function () {
      setIframeHeight();
  });
  $(window).resize( function () {
      setIframeHeight();
  });
</script> 

The first half is from ???, and works when there is html in the iframe. The second half sets the iframe to page height (not content height), when iframes class is iframe_fullHeight. You can use this if the content is a PDF or other such like, but you have to set the class. Also can only be used when being full height is appropriate.

Note: for some reason, when it recalculates after window resize, it gets height wrong.


N
Neil Thompson
function autoResize(id){
    var newheight;
    var newwidth;

    if(document.getElementById){
        newheight=document.getElementById(id).contentWindow.document.body.scrollHeight;
        newwidth=document.getElementById(id).contentWindow.document.body.scrollWidth;
    }

    document.getElementById(id).height=(newheight) + "px";
    document.getElementById(id).width=(newwidth) + "px"; 
}

add this to your iframe: onload="autoResize('youriframeid')"


А
Айдън Бейтулов
jq2('#stocks_iframe').load(function(){
var iframe_width = jq2('#stocks_iframe').contents().outerHeight() ; 
jq2('#stocks_iframe').css('height',iframe_width); });

<iframe id='stocks_iframe' style='width:100%;height:0px;' frameborder='0'>

M
Mark Amery

I did it with AngularJS. Angular doesn't have an ng-load, but a 3rd party module was made; install with bower below, or find it here: https://github.com/andrefarzat/ng-load

Get the ngLoad directive: bower install ng-load --save

Setup your iframe:

<iframe id="CreditReportFrame" src="about:blank" frameborder="0" scrolling="no" ng-load="resizeIframe($event)" seamless></iframe>

Controller resizeIframe function:

$scope.resizeIframe = function (event) {
    console.log("iframe loaded!");
    var iframe = event.target;
    iframe.style.height = iframe.contentWindow.document.body.scrollHeight + 'px';
};

A
AlphaMycelium

I wanted to make an iframe behave like a normal page (I needed to make a fullscreen banner inside an iframe element), so here is my script:

    (function (window, undefined) {

    var frame,
        lastKnownFrameHeight = 0,
        maxFrameLoadedTries = 5,
        maxResizeCheckTries = 20;

    //Resize iframe on window resize
    addEvent(window, 'resize', resizeFrame);

    var iframeCheckInterval = window.setInterval(function () {
        maxFrameLoadedTries--;
        var frames = document.getElementsByTagName('iframe');
        if (maxFrameLoadedTries == 0 || frames.length) {
            clearInterval(iframeCheckInterval);
            frame = frames[0];
            addEvent(frame, 'load', resizeFrame);
            var resizeCheckInterval = setInterval(function () {
                resizeFrame();
                maxResizeCheckTries--;
                if (maxResizeCheckTries == 0) {
                    clearInterval(resizeCheckInterval);
                }
            }, 1000);
            resizeFrame();
        }
    }, 500);

    function resizeFrame() {
        if (frame) {
            var frameHeight = frame.contentWindow.document.body.scrollHeight;
            if (frameHeight !== lastKnownFrameHeight) {
                lastKnownFrameHeight = frameHeight;

                var viewportWidth = document.documentElement.clientWidth;
                if (document.compatMode && document.compatMode === 'BackCompat') {
                    viewportWidth = document.body.clientWidth;
                }

                frame.setAttribute('width', viewportWidth);
                frame.setAttribute('height', lastKnownFrameHeight);

                frame.style.width = viewportWidth + 'px';
                frame.style.height = frameHeight + 'px';
            }
        }
    }

    //--------------------------------------------------------------
    //  Cross-browser helpers
    //--------------------------------------------------------------

    function addEvent(elem, event, fn) {
        if (elem.addEventListener) {
            elem.addEventListener(event, fn, false);
        } else {
            elem.attachEvent("on" + event, function () {
                return (fn.call(elem, window.event));
            });
        }
    }

})(window);

The functions are self-explanatory and have comments to further explain their purpose.


May be some need an explanation, at least how to use it. And what it does. (-1)
This works for me on FF, but I agree with @richard that some explanation will go some way towards getting this accepted as an answer.
there is like.... 1 comment, on the obvious thing. The actual stuff i don't understand has no comments. No mention if this is affected by SOP. Worst, it uses setTimeout - imagine if i was on a really slow connection...
O
Owen

I've had problems in the past calling iframe.onload for dynamically created iframes, so I went with this approach for setting the iframe size:

iFrame View

var height = $("body").outerHeight();
parent.SetIFrameHeight(height);

Main View

SetIFrameHeight = function(height) {
    $("#iFrameWrapper").height(height);
}

(this is only going to work if both views are in the same domain)


h
henrebotha
<script type="text/javascript">
  function resizeIframe(obj) {
    obj.style.height = 0;
    obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
  }
</script>

this is not working for chrome. But working for firefox.


V
Vijay Chouhan

This option will work 100%

<iframe id='iframe2' src="url.com" frameborder="0" style="overflow: hidden; height: 100%; width: 100%; position: absolute;" height="100%" width="100%"></iframe>

@all, Please make comment if it does not work for you instead of mark negative, because its working on many websites.
All this does is makes a fullscreen iframe, which is definitely not what most people want. This also goes against the HTML5 spec, which says that height and width of an iframe must be in pixels, not percent (however percent is perfectly fine for HTML 4.01). See developer.mozilla.org/en/docs/Web/HTML/Element/iframe
The only one so far to (sort of) work. It fixed the height, but pushed it self right covering my right side bar. (even with the width stuff removed)
It blocks the clicks behind this iframe