In my project for ADEME (national environment agency), we need to display our app in an iframe to embedded it as a tool inside a marketing campaign. The fact that there is two different webapp should be transparent for the user and we absolutely want to avoid double scroll : one for the website and one for the iframe.
Then, we need to display the content of the iframe in a box which fit to the size of the embedded webapp in the iframe. We don’t want to fix a size of the box because it would be : less flexible to display content, difficult to maintain when the content of the iframe will change even a little bit, a blocker to upgrade safely the dependencies which can have display effect.
After some investigation, I found 2 ways to do it
Use your own JS
Create a piece of javascript in the iframe which will post a message with the height of the page, written in typescript below :
function postHeightSize(): void {
const target: Window | undefined = parent.postMessage ? parent : undefined
if (target && document.body.scrollHeight) {
target.postMessage(document.body.scrollHeight, "*")
}
}
window.addEventListener("load", function (): void {
postHeightSize()
})
And a piece of javascript which will interpret it in the page which embed the iframe : receive this posted message and apply the height received to the iframe block
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<iframe id="myiframe" src="http://exemple-iframe.com/?iframe" style="width: 100%;border: none;" allow="geolocation"></iframe>
</body>
<script>
function receiveSize(e){
console.error(e);
if(e.origin === "http://exemple-iframe.com/"){
var newHeight = e.data + 40;
document.getElementById("myiframe").style.height = newHeight + "px";
}
}
window.addEventListener("message", receiveSize, false);
</script>
</html>
Here is the PR I made with this version : manage a resizable iframe #59
Use iframe-resizer library
Searching a little bit deeper, I found a library which resize the iframe for you, without custom code : iframe-resizer, thank you @David J. Bradshaw
Actually it use the same process of posting messages but it will handle the edge case like :
- Works with multiple and nested iFrames.
- Detects changes to the DOM that can cause the page to resize using MutationObserver.
But also a lot more option you can read in the documentation.
Here is the implementation, in the webapp embed as an iframe
<html>
<head>...</head>
<body>
...
<script
src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.6/iframeResizer.contentWindow.js"
integrity="sha512-hBWsS94l8+snzSPo759jDKZ3z3jn3WT4snJZTBaeMPbrCGzDrYdl2pN9EaXjh6IqEZC7wF10qcmp42TPRVgAYQ=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
defer
></script>
</body>
</html>
And in the page which embed the iframe :
<!DOCTYPE html>
<html>
<head>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.6/iframeResizer.min.js"
integrity="sha512-f0wd6UIvZbsjPNebGx+uMzHmg6KXr1jWvumJDYSEDmwYJYOptZ0dTka/wBJu7Tj80tnCYMKoKicqvZiIc9GJgw=="
crossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
</head>
<body>
...
<iframe
id="myiframe"
src="http://example-iframe/?iframe"
style="width: 100%;border: none;"
allow="geolocation"
></iframe>
...
<script>
document.getElementById('myiframe').addEventListener('load', function () {
iFrameResize({
heightCalculationMethod: 'documentElementOffset',
maxWidth: 800,
}, '#myiframe')
})
</script>
</body>
</html>
Here is the PR I made with the iframe-resizer library : Manage ifarme resize with iframe resize library #72
Conclusion
I really prefer the JS library version, it uses less code, it is more flexible, furthermore, I don’t need to maintain it.
Less code, less bugs