Resizing an iframe based on content

后端 未结 21 2482
南方客
南方客 2020-11-21 07:40

I am working on an iGoogle-like application. Content from other applications (on other domains) is shown using iframes.

How do I resize the iframes to fit the heigh

相关标签:
21条回答
  • 2020-11-21 07:57

    Work with jquery on load (cross browser):

     <iframe src="your_url" marginwidth="0"  marginheight="0" scrolling="No" frameborder="0"  hspace="0" vspace="0" id="containiframe" onload="loaderIframe();" height="100%"  width="100%"></iframe>
    
    function loaderIframe(){
    var heightIframe = $('#containiframe').contents().find('body').height();
    $('#frame').css("height", heightFrame);
     }  
    

    on resize in responsive page:

    $(window).resize(function(){
    if($('#containiframe').length !== 0) {
    var heightIframe = $('#containiframe').contents().find('body').height();
     $('#frame').css("height", heightFrame);
    }
    });
    
    0 讨论(0)
  • 2020-11-21 07:58

    I'm implementing ConroyP's frame-in-frame solution to replace a solution based on setting document.domain, but found it to be quite hard determining the height of the iframe's content correctly in different browsers (testing with FF11, Ch17 and IE9 right now).

    ConroyP uses:

    var height = document.body.scrollHeight;
    

    But that only works on the initial page load. My iframe has dynamic content and I need to resize the iframe on certain events.

    What I ended up doing was using different JS properties for the different browsers.

    function getDim () {
        var body = document.body,
            html = document.documentElement;
    
        var bc = body.clientHeight;
        var bo = body.offsetHeight;
        var bs = body.scrollHeight;
        var hc = html.clientHeight;
        var ho = html.offsetHeight;
        var hs = html.scrollHeight;
    
        var h = Math.max(bc, bo, bs, hc, hs, ho);
    
        var bd = getBrowserData();
    
        // Select height property to use depending on browser
        if (bd.isGecko) {
            // FF 11
            h = hc;
        } else if (bd.isChrome) {
            // CH 17
            h = hc;
        } else if (bd.isIE) {
            // IE 9
            h = bs;
        }
    
        return h;
    }
    

    getBrowserData() is browser detect function "inspired" by Ext Core's http://docs.sencha.com/core/source/Ext.html#method-Ext-apply

    That worked well for FF and IE but then there were issues with Chrome. One of the was a timing issue, apparently it takes Chrome a while to set/detect the hight of the iframe. And then Chrome also never returned the height of the content in the iframe correctly if the iframe was higher than the content. This wouldn't work with dynamic content when the height is reduced.

    To solve this I always set the iframe to a low height before detecting the content's height and then setting the iframe height to it's correct value.

    function resize () {
        // Reset the iframes height to a low value.
        // Otherwise Chrome won't detect the content height of the iframe.
        setIframeHeight(150);
    
        // Delay getting the dimensions because Chrome needs
        // a few moments to get the correct height.
        setTimeout("getDimAndResize()", 100);
    }
    

    The code is not optimized, it's from my devel testing :)

    Hope someone finds this helpful!

    0 讨论(0)
  • 2020-11-21 07:58

    I have an easy solution and requires you to determine the width and height in the link, please try (It works with most browsers):

    <a href='#' onClick=" document.getElementById('myform').src='t2.htm';document.getElementById('myform').width='500px'; document.getElementById('myform').height='400px'; return false">500x400</a>
    
    0 讨论(0)
  • 2020-11-21 07:59

    This is an old thread, but in 2020 it's still a relevant question. I've actually posted this answer in another old thread as well^^ (https://stackoverflow.com/a/64110252/4383587)


    Just wanted to share my solution and excitement. It took me four entire days of intensive research and failure, but I think I've found a neat way of making iframes entirely responsive! Yey!

    I tried a ton of different approaches... I didn't want to use a two-way communication tunnel as with postMessage because it's awkward for same-origin and complicated for cross-origin (as no admin wants to open doors and implement this on your behalf).

    I've tried using MutationObservers and still needed several EventListeners (resize, click,..) to ensure that every change of the layout was handled correctly. - What if a script toggles the visibility of an element? Or what if it dynamically preloads more content on demand? - Another issue was getting an accurate height of the iframe contents from somewhere. Most people suggest using scrollHeight or offsetHeight, or combination of it by using Math.max. The problem is, that these values don't get updated until the iframe element changes its dimensions. To achieve that you could simply reset the iframe.height = 0 before grabbing the scrollHeight, but there are even more caveats to this. So, screw this.

    Then, I had another idea to experiment with requestAnimationFrame to get rid of my events and observers hell. Now, I could react to every layout change immediately, but I still had no reliable source to infer the content height of the iframe from. And theeen I discovered getComputedStyle, by accident! This was an enlightenment! Everything just clicked.

    Well, see the code I could eventually distill from my countless attempts.

    function fit() {
        var iframes = document.querySelectorAll("iframe.gh-fit")
    
        for(var id = 0; id < iframes.length; id++) {
            var win = iframes[id].contentWindow
            var doc = win.document
            var html = doc.documentElement
            var body = doc.body
            var ifrm = iframes[id] // or win.frameElement
    
            if(body) {
                body.style.overflowX = "scroll" // scrollbar-jitter fix
                body.style.overflowY = "hidden"
            }
            if(html) {
                html.style.overflowX = "scroll" // scrollbar-jitter fix
                html.style.overflowY = "hidden"
                var style = win.getComputedStyle(html)
                ifrm.width = parseInt(style.getPropertyValue("width")) // round value
                ifrm.height = parseInt(style.getPropertyValue("height"))
            }
        }
    
        requestAnimationFrame(fit)
    }
    
    addEventListener("load", requestAnimationFrame.bind(this, fit))
    

    That is it, yes! - In your HTML code write <iframe src="page.html" class="gh-fit gh-fullwidth"></iframe>. The gh-fit is a just fake CSS class, used to identify which iframe elements in your DOM should be affect by the script. The gh-fullwidth is a simple CSS class with one rule width: 100%;.

    The above script automatically fetches all iframes from the DOM, that have a .gh-fit class assigned. It then grabs and uses the pre-calculated style values for width and height from document.getComputedStyle(iframe), which always contain a pixel-perfect size of that element!!! Just perfect!

    Note, this solution doesn't work cross-origin (nor does any other solution, without a two-way communication strategy like IFrameResizer). JS simply can't access the DOM of an iframe, if it doesn't belong to you.

    The only other cross-origin solution I can think of, is to use a proxy like https://github.com/gnuns/allorigins. But this would involve deep-copying every request you make - in other words - you 'steal' the entire page source code (to make it yours and let JS access the DOM) and you patch every link/path in this source, so that it goes through the proxy as well. The re-linking routine is a tough one, but doable.

    I'll probably try myself at this cross-origin problem, but that's for another day. Enjoy the code! :)

    0 讨论(0)
  • 2020-11-21 07:59

    Using jQuery:

    parent.html

    <body>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <style>
    iframe {
        width: 100%;
        border: 1px solid black;
    }
    </style>
    <script>
    function foo(w, h) {
        $("iframe").css({width: w, height: h});
        return true;  // for debug purposes
    }
    </script>
    <iframe src="child.html"></iframe>
    </body>
    

    child.html

    <body>
    <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
    <script>
    $(function() {
        var w = $("#container").css("width");
        var h = $("#container").css("height");
    
        var req = parent.foo(w, h);
        console.log(req); // for debug purposes
    });
    </script>
    <style>
    body, html {
        margin: 0;
    }
    #container {
        width: 500px;
        height: 500px;
        background-color: red;
    }
    </style>
    <div id="container"></div>
    </body>
    
    0 讨论(0)
  • 2020-11-21 08:00

    Finally I found some other solution for sending data to parent website from iframe using window.postMessage(message, targetOrigin);. Here I explain How I did.

    Site A = http://foo.com Site B = http://bar.com

    SiteB is loading inside the siteA website

    SiteB website have this line

    window.parent.postMessage("Hello From IFrame", "*"); 
    

    or

    window.parent.postMessage("Hello From IFrame", "http://foo.com");
    

    Then siteA have this following code

    // Here "addEventListener" is for standards-compliant web browsers and "attachEvent" is for IE Browsers.
    var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
    var eventer = window[eventMethod];
    
    
    var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
    
    // Listen to message from child IFrame window
    eventer(messageEvent, function (e) {
       alert(e.data);
       // Do whatever you want to do with the data got from IFrame in Parent form.
    }, false); 
    

    If you want to add security connection you can use this if condition in eventer(messageEvent, function (e) {})

    if (e.origin == 'http://iframe.example.com') {
        alert(e.data); 
        // Do whatever you want to do with the data got from IFrame in Parent form.
    }
    

    For IE

    Inside IFrame:

     window.parent.postMessage('{"key":"value"}','*');
    

    Outside:

     eventer(messageEvent, function (e) {
       var data = jQuery.parseJSON(e.data);
       doSomething(data.key);
     }, false);
    
    0 讨论(0)
提交回复
热议问题