Size iframe to fit its content

by Gregg Tavares

HTML

<h1>page with iframe that sizes iframe to fit iframe's content</h1>
<iframe></iframe>


<script type="not-js" id="iframe-content">
<body>
 <h2>iframe content</h2>
 <button type="button">Add more content to iframe</button>
</body>
<!-- need to name this iscript so it doesn't get seen by main page -->
<iscript>
// this script needs to be in the iframe but S.O. snippets can't do that
// so we'll inject it via blob
{
  const observer = new ResizeObserver(() => {
    window.parent.postMessage({
      width: document.body.scrollWidth,
      height: document.body.scrollHeight,
    });
  });
  observer.observe(document.body);
  
  document.querySelector('button').addEventListener('click', () => {
    const elem = document.createElement('pre');
    elem.textContent = `${new Date()}
filler
more filler
bla bla
bla
`;
   document.body.appendChild(elem);
  });
}
</iscript>
</script>

CSS

iframe {
  border: none;
  background-color: #eee;
}

JavaScript

window.addEventListener('message', (e) => {
  const {width, height} = e.data;
  iframeElem.style.width = `${width}px`;
  iframeElem.style.height = `${height}px`;
});


const iframeElem = document.querySelector('iframe');

// Note: using a blob so this can run in a snippet but just normal
// src="path/to/helper" would work
const iframeHTML = document.querySelector('#iframe-content').text.replace(/iscript/g, 'script');
const blob = new Blob([iframeHTML], {type: 'text/html'});
iframeElem.src = URL.createObjectURL(blob);