Setting Iframe Height: Cross-Domain Version

Elsewhere we have described and demonstrated how you can use JavaScript to set the height of an iframe to match the height of its content. Here we provide the JavaScript and an example to show how you can use postMessage to accomplish this when the containing document and iframed document are on different domains.

Due to the constraints imposed by JavaScript's Same Origin Policy, the document containing the iframe is not able to access the document inside the iframe or any of the properties needed to determine its height. However, the document in the iframe can determine its own height onload and pass it to the containing document using postMessage. The containing document includes a message event handler to receive the height passed from the iframed document and set the height of the iframe accordingly.

JavaScript in Iframed Document

The following JavaScript is included in iframed documents in order to send their height to the containing (parent) document.

// Get height of document
function getDocHeight(doc) {
    doc = doc || document;
    // from http://stackoverflow.com/questions/1145850/get-height-of-entire-document-with-javascript
    var body = doc.body, html = doc.documentElement;
    var height = Math.max( body.scrollHeight, body.offsetHeight, 
        html.clientHeight, html.scrollHeight, html.offsetHeight );
    return height;
}

// send docHeight onload
function sendDocHeightMsg(e) {
    var ht = getDocHeight();
    parent.postMessage( JSON.stringify( {'docHeight': ht} ), '*' );
}

// assign onload handler 
if ( window.addEventListener ) {
    window.addEventListener('load', sendDocHeightMsg, false);
} else if ( window.attachEvent ) { // ie8
    window.attachEvent('onload', sendDocHeightMsg);
}

The getDocHeight function determines the height of the document. It should work in virtually all current browsers whether they are displaying pages in standards or quirks mode. The sendDocHeightMsg function is assigned to the onload event. JSON.stringify is applied to the document height, and postMessage is used to send it to the parent document.

Notice that the asterisk is used for the second argument to postMessage so that you can send the height of the document to any domain set up to receive it. You can specify a particular domain if you prefer.

JavaScript in Parent Document

The document containing the iframe includes an event handler to receive messages from iframed documents about their height as shown here:

// modified from same-domain version at http://www.dyn-web.com/tutorials/iframes/height/
function setIframeHeightCO(id, ht) {
    var ifrm = document.getElementById(id);
    ifrm.style.visibility = 'hidden';
    // some IE versions need a bit added or scrollbar appears
    ifrm.style.height = ht + 4 + "px";
    ifrm.style.visibility = 'visible';
}


// iframed document sends its height using postMessage
function handleDocHeightMsg(e) {
    // check origin
    if ( e.origin === 'http://www.example.com' ) {
        // parse data
        var data = JSON.parse( e.data );
        // check data object
        if ( data['docHeight'] ) {
            setIframeHeightCO( 'ifrm', data['docHeight'] );
        } else if ( data['href'] ) { 
            setIframe('ifrm', data['href'] );
        }
    }
}

// assign message handler
if ( window.addEventListener ) {
    window.addEventListener('message', handleDocHeightMsg, false);
} else if ( window.attachEvent ) { // ie8
    window.attachEvent('onmessage', handleDocHeightMsg);
}

Perhaps you noticed that when the iframed document sends its height to the parent, it sends it as an object literal with a docHeight property. The message handler checks the data object for this property. Notice that it also checks for an href property. The example demonstrates how this is used for links in the iframed document.