Resize iframe based on content

March 17, 2010 by: admin

One thing that many are using easyXDM (and other cross-domain hacks) for, is to dynamically change the size of embedded iframes based on the contents size, so as to avoid the scrollbars.

With easyXDM this is really easy:

Instead of embedding the iframe using plain HTML like ..

<iframe src="http://......."></iframe>

.. you do it using easyXDM ..

<br /><!-- use css to style this and its contained iframe --><br /><div id="container">/div><br />
new easyXDM.Socket({
    remote: "http://provider.easyxdm.net/example/resized_iframe.html",
    container: document.getElementById("container"),
    onMessage: function(message, origin){
        this.container.getElementsByTagName("iframe")[0].style.height = message + "px";
    }
});

.. and then in the document to embed, after the content, you put

var socket = new easyXDM.Socket({
    onReady:  function(){
        socket.postMessage(document.body.scrollHeight)
   }
});

You can see at demo of this in action here.

If you plan on navigating the inner window, be aware that this will break the connection and subsequent pages won’t cause the iframe to resize. Therefor the example uses an intermediary frame to facilitate this.

  • Ryan A

    I found you can also get the context by doing something like…

    window.parent.parent.$(“iframe”).css(“height”, obj.value + “px”)

    I also found that I could not get this to work unless I added the remote param on both sides. Whichever side didnt have it would throw an error.

    • http://kinsey.no/ Øyvind Sean Kinsey

      Then you are doing something wrong ;)

      Øyvind Sean Kinsey
      San Francisco, CA

  • Glennnall

    was able to make this work nicely across domains with the test pages, and with other straight html pages, but can’t make it resize when i call a WordPress index.php file – PLEASE someone explain why…???

  • Glennnall

    well it doesn’t like WordPress, i can attest to that. i’ve found NO reason it won’t resize, and i’ve copied everything necessary from the test files to the appropriate WP files. this can leave a bitter taste, don’t ya know!!!

  • novanewsbg

    it works only for subdomains. That’s useless! There are easier ways to solve this for subdomains 

    • http://kinsey.no/ Øyvind Sean Kinsey

      Actually it works across domains, not only across subdomains (no specific support for this actually)

  • electromel

    Great script, work fine on FF, chrome, ie9 and beyond but on ie8 (used with iframe_intermediate.html) the iframe.onload doesn’t seem to get fired. Then there is no postMessage…
    Any idea?

    • electromel

      forgot to say, I’m working on cross domain

    • electromel

      Finally I find a solution
      Here is an update of the script part of resize_intermediate.htm working win ie6 et beyond

                      var iframe;        var timer;        var socket;        function SendSizeInfo() {        var d = iframe.contentWindow.document;        var originalHeight = d.body.clientHeight || d.body.offsetHeight || d.body.scrollHeight;        // We want to monitor the document for resize events in case of the use of accordions and such,        // but unfortunately only the window node emits the resize event, and we need the body’s.        // The only solution then is to use polling..        // Lets start the polling if not all ready started        if (!timer) {        timer = setInterval(function () {        try {        var d = iframe.contentWindow.document;        var newHeight = d.body.clientHeight || d.body.offsetHeight || d.body.scrollHeight;        if (newHeight != originalHeight) {        // The height has changed since last we checked        originalHeight = newHeight;        socket.postMessage(originalHeight);        }        } catch (e) {        // We tried to read the property at some point when it wasn’t available        }        }, 300);        }        // Send the first message        socket.postMessage(originalHeight);        };        //var iframe;        socket = new easyXDM.Socket({        swf: “./easyxdm.swf”,        onReady: function () {        iframe = document.createElement(“iframe”);        iframe.frameBorder = 0;        iframe.style.width = “100%”;        iframe.style.height = “100%”;        document.body.appendChild(iframe);        iframe.src = easyXDM.query.url;        //var timer;        if (iframe.addEventListener)        iframe.addEventListener(“load”, SendSizeInfo, false)        else if (iframe.attachEvent)        iframe.attachEvent(“onload”, SendSizeInfo)        else if (document.getElementById)        iframe.onload = SendSizeInfo        },        onMessage: function (url, origin) {        iframe.src = url;        }        });       

      • Cedlemlaro

        Dear Electromel, thank you so much I have been trying to fix it for more than 3 month!!! I cant believe, it is now working on IE8!

        Could you please add me on Skype (my username is cedlemlaro), I would really like to know why it was not working.

  • Scotty Fitz

    Hey Oyvind !

    Great library, but please, please – can you have a quick look at this and see what you think ?
    I  give my iFrame code to clients, so they can display the dynamic content from my site. I’d like the iFrame that lives on their page to resize to fit my content.
    I followed the instructions above, but maybe I am missing something?

    I don’t get any errors, but the iFrame stays the default height (150px).

    The code I give my client site is :

      Â
      Â
            var transport = new easyXDM.Socket({
                remote: “http://www.lipsum.com/”,
                container: “container”,
                onMessage: function (message, origin) {
                    this.container.getElementsByTagName(“iframe”)[0].style.height = message + “px”;
                }
            });
      Â
    ________________________________________________________________________________________________

    This is the code that goes on the document I want to embed :

        var socket = new easyXDM.Socket({    onReady: function () { socket.postMessage(document.body.scrollHeight) }            });

    I’m hoping there is something simple I’m doing wrong…
    Can you PLEASE help Oyvind ?

    Thanks a lot.

  • aendrew

    I was able to get this working by putting the socket code in my theme’s footer template, and was pleasantly surprised that clicking iframe’d links resulted in those also changing the window’s height — without having created any sort of intermediary page. Is there any reason why this shouldn’t work that I should be aware of? Or am I just misunderstanding the concept of intermediary frames in this context?

  • Ajeftink

    So I have the code working but have two bugs…1. When the Iframe is loaded it sets to width to 300px.  I’ve added code to change the width afterwards but why is it setting the width to 300px?  Is there something in your code doing that or is that problem on my end?

    2.  Navigating to a different page on the same domain and then returning to the page with with the iframe results in the iframe height being almost twice as much as it should be.  I don’t know why this is happening.