Categories

Cross-Domain Iframe Resize

Posted on: August 15, 2014 by Dimitar Ivanov

The problem

Normally, documents on different pages are able to communicate between each other only if their domains, protocols and ports match up. HTML 5 specification comes with window.postMessage, which provides cross-domain communication between scripts.

Syntax

window.postMessage(message, targetOrigin, [transfer]);

message
Messages can be nested objects and arrays, can contain JavaScript values (strings, numbers, Dates, etc), and can contain certain data objects such as File Blob, FileList, and ArrayBuffer objects.
targetOrigin
The value must be either asterisk *, slash / or absolute URL. Otherwise a SyntaxError exception will be throw. If you know the window location, you should always provide this specific location instead of just putting an asterisk *
transfer (Optional)
These objects are transferred with the message, and they are no longer usable on the sending side.

Register an event handler for incoming events

Always verify the sender's identity using the origin property. Skipping this step enables cross-site scripting attacks.

<script type="text/javascript">
window.addEventListener("message", myListener, false);

function myListener(event) {
    if (event.origin !== "https://remote-domain.com:8080") {
        return;
    }
    //do something
}
</script>

How to resize iframe

Document A - contain an iframe; and expects a message from document B.

<!doctype html>
<html>
    <head>
        <title>Document A</title>
        <meta charset="utf-8">
    </head>
    <body>
        <iframe src="https://remote-domain.com:8080/document-B.html" id="zino_iframe"></iframe>
        <script type="text/javascript">
        var zino_resize = function (event) {
            if (event.origin !== "https://remote-domain.com:8080") {
                return;
            }
            var zino_iframe = document.getElementById('zino_iframe');
            if (zino_iframe) {
                zino_iframe.style.height = event.data + "px";
            }
        };
        if (window.addEventListener) {
            window.addEventListener("message", zino_resize, false);
        } else if (window.attachEvent) {
            window.attachEvent("onmessage", zino_resize);
        }
        </script>
    </body>
</html>

Document B - post a message to document A. In our case the message is the iframe height.

<!doctype html>
<html>
    <head>
        <title>Document B</title>
        <meta charset="utf-8">
        <script type="text/javascript">
        function iframe_resize(){
            var body = document.body,
            html = document.documentElement,
            height = Math.max(body.scrollHeight, body.offsetHeight, 
	        html.clientHeight, html.scrollHeight, html.offsetHeight);
            if (parent.postMessage) {
                parent.postMessage(height, "https://my-domain.com");
            }
        }
        </script>
    </head>
    <body onload="iframe_resize();">
        <h4>Document B</h4>
	<p>Cross-Domain Iframe</p>
    </body>
</html>

Browser compatibility

Chrome 1+, Firefox 6+, IE8+, Opera 9.5+, Safari 4+

Make your website more secure by using the HTTP Headers for Wordpress, and never face a cross-origin issue again. Oh yes, it's FREE.
See also
Further reading
Social sharing

If you have questions about cross domain iframe resize, leave a comment below. And do not be shy to share this article. Thanks for reading.


9 Comments

SteveC
Thanks for this awesome, light-weight, cross browser example. I spent a bunch of time trying to figure some others out and this was by far the simplest for me to implement.
antonio correia
antonio correia April 26, 2015 at 05:53 am
I enjoy your work on publish this article. I have spent more than a day looking for it.
My iframe is into wordpress page and I donĀ“t know only part 2 (document b) seems being work. I put alert in it and it show the height of document b.
But document a, who has the frame doen't change height parameter.
Any tip to solve the problem?'
thanks
Dimitar Ivanov
@antonio, thank you.

You may see an example at: http://zinoui.com/demo/iframe-resize/document-A.html
Lee Braham
I have 'source.html' page (having code of Document B) on source domain (say source.com) and 'iframe.html' page (having code of Document A) on other domain (say iframe.com). I changed
http://remote-domain.com:8080 from iframe.html
and
http://my-domain.com from source.html
with
http://source.com .
But, I don't have an auto height resizing iframe.
While replying, plz keep in mind I'm not a developer but a blogger.
Ferdy
Very nice!
If it possible works with two or more iframes??
Ken Knight
This seems to work great if document B never navigates to a new page, however, let's say that you need Doc B, C , D to navigate between each other. Whenever the Math.max() function is called inside each of these pages with the suggested elements of the example, the height never decrease to a value less than the largest height calculated between any of the pages. Any thoughts on this?
Ken Knight
Figured out a work around. Instead of using max function on the various html / body elements etc, I just wrapped a div with an id around the content and then get the offsetHeight of that div and pass it to the parent. Works like a champ this way.
Dc
Hello,

Great! This is the code I am looking. Thank you. I have a little bit question, I have implemented the code to the iframe page and put the other code to the page I am to call. First, the height is okay, then when I select other page inside the iframe with height is greater than the previous page I have selected, the iframe height gets the most height and remains even I selected a page that is smaller content height, so the iframe will looks like there is much space below. Is there possible solution to get all the content height dynamically to get rid of the space when I have selected a page with greater height?

Thank you and regards.
Benassi
Though helpful in some situations, you need to have control over the nested domain in order to post a message to be received by the listener in the parent. There are scenarios where iframe is containing a domain that you have no control over. I am dealing with such a scenario now where the iframe contains a Hosted Page solution from a credit card handler where we use tokenization to keep credit cards on file without directly handling the card info. We have no control over hosted page code and so can issue no messages on our own.

Leave a comment

Captcha