嘿, 我是Mofei!
Cross-Domain iframe Height Adaptive Implementation Solution

Background

Most application platforms insert cross-site applications through iframes. Most of the time, this can meet the requirements, but when it comes to some special applications, their height is not fixed and varies with the content of the application. Although scroll bars may appear, this can somewhat affect the aesthetics of the page. So, is there a solution that allows the height of the iframe to change with its content?

Attempts

  • Get the content height of the iframe via JavaScript. Set the iframe's height to be the same as the content height.

    This solution works flawlessly in the same domain, but the drawback is that it is powerless in a cross-domain scenario.

  • Introduce a piece of JS inside the iframe to monitor the height of the iframe content in real-time and send it to the server. The embedding page continuously retrieves the height from the server and sets it.

    This solution does solve the problem, but there are some frustrating aspects.

    • Constantly sending data to the server increases the server's workload.

    • JavaScript continuously requests the server to get the new height. This constant polling is indeed annoying.

  • Building on the above, avoiding the server would be a good method, but how can we bypass the server?

    We tried cookies, local storage, etc., hoping for a solution that could bypass the domain restrictions, but all ended in failure.

    Finally, a sudden inspiration: if we could use a layer of proxy as a bridge to solve the cross-domain problem, wouldn’t all issues be easily resolved?

Solution

Domain! Through the experiments above, we have inserted a piece of JS into the iframe, which means we can control the content inside the iframe freely. At this point, if we insert an iframe address into the iframe that is the same domain as the outer page, can they communicate? Thus, we have the following model.

a.com/index.html
<body>
    <iframe src="b.com">
        content
        <script src="a.com/iframe.js" type="text/javascript"> </script>
        <!-- The iframe added by JavaScript -->
        <iframe src="a.com/height.html"></iframe>
    </iframe>
</body>
a.com/iframe.js
    var height = document.height;
    var iframe2 = document.createElement('iframe');
    iframe2.height = 0;
    iframe2.src = "http://a.com/height.html";
    document.body.appendChild(iframe2);
a.com/height.html
<body>
    <script type="text/javascript">
         alert(top.document.getElementsByTagName('iframe')[0])
    </script>
</body>

From the above code, we are amazed to find that height.html can indeed access elements inside a.com/index.html.

Implementation

Therefore, the problem becomes simple; just pass the height of the iframe to index.html, and rewrite the code as follows.

a.com/iframe.js

    var height = document.height;
    var iframe2 = document.createElement('iframe');
    iframe2.height = 0;
    iframe2.style.display = 'none';
    iframe2.src = "http://127.0.0.1/test3.html?height=" + document.height + '&v' + Math.random();
    document.body.appendChild(iframe2);
    setInterval(function() {
        if(document.height!=height){
            iframe2.src = "http://a.com/height.html?height=" + document.height + '&v' + Math.random();
            height=document.height;
        }
    }, 10);
a.com/height.html
<body> 
    <script type="text/javascript">
        var height=/height=(
\d+)&/.exec(location.href)[1];
        top.document.getElementsByTagName('iframe')[0].height = parseInt(height);
    </script>
</body>

Summary

The problem is solved, and I feel relieved. The main idea of this solution is to create a same-origin iframe within the iframe and pass the iframe height through the address to establish communication between the iframe and the outside world, achieving height adaptability.

THE END

More Articles You Might Be Interested In

Your feedback will help me write better posts—looking forward to it!

avatar

Mofei's Friend (Click to edit)

The world is big, say something!

HI. I AM MOFEI!

NICE TO MEET YOU!