iframes are principally used for loading external content onto an existing page. But what if you want to have local content inside an iframe? This only seems possible with a little JavaScript but there is a way to do it.

This need is an edge case. Why would you want to load local content inside an iframe? Surely it would be better to just place it inside the existing page structure? Well, in my instance I wanted to see isolated code (HTML/CSS) snippets on an existing page, rendered by an external style sheet. Like embedding a Codepen/JSBin onto the page if you will but with local, not external content.

Although it’s trivial to bring in a separate style sheet that is relevant to the code snippet (just by adding another link in the <head>), the existing CSS could/would still apply to the code snippet too. Even ‘normalize’ styles and the like would make subtle changes to the appearance of the rendered snippets. It didn’t create the ‘sandbox’ environment I was looking for.

Scope with name-spacing?

Obviously it’s possible to pseudo-scope CSS crudely by name-spacing. However, as already mentioned, the external CSS typically has its own global defaults set (default styling for elements) so it never truly isolates what gets applied.

Local content inside an iframe?

To truly limit the reach of the external styles we could use an iframe. After all, an iframe is a separate document rendered inside the existing one. However, this presents further problem; iframes are for showing external content on a page (our primitive page within a page description).

It doesn’t seem possible to author an iframe inside an existing page that contains only local content. For example, adding this inside an existing HTML page does not work:

<iframe width="100%" height="100%" src="about:blank">
	<!doctype html>
		<head>
			<title>Test local content</title>
		</head>
		<body>
			<p>hello</p>
		</body>
	</html>
</iframe>

After trying many things, I still wasn’t able to author the iframe in advance that included only local content. Is there a way? I’d love to do this without JS if possible. In the meantime time is money so I needed to press on and find a solution.

Add local content to an iframe with JavaScript?

I stumbled upon this blog post. It gave me the help I needed to to enable the local content to be added into the iframe via JavaScript.

The plan: sandbox with JavaScript and iframes

The problem can be solved by placing the needed content for the iframe contents in a hidden div and then appending that content in (with JavaScript) to the waiting iframe. This solution has worked well for my needs.

Here’s a the JavaScrip to achieve this, hopefully the comments explain what is going on:

// Create a new blank iframe
var newIframe = document.createElement('iframe');
// Set attributes for iFrame (do whatever suits)
newIframe.width = '100%'; newIframe.height = '100%';
// This for the src makes it 'friendly'
newIframe.src = 'about:blank'; 

// Use whatever method is needed to insert the iframe where you want it 
document.body.appendChild(newIframe);
// Make this reference your hidden div containing the markup you want to insert
var getHTML = $('#HTMLblock').html();
// List any CSS you want to reference within the iframe
var CSS = '<link rel="stylesheet" href="https://external.com/css/styles.css">';
// List any JS you want to reference within the iframe
var JS = '<script src="http://external.com/js/plugins.js"></script>';
// Now sticch it all together into one thing to insert into the iframe
var myContent = '<!DOCTYPE html>' + '<html><head><title>Rendered HTML from Pattern</title>' + CSS + '</head><body>' + getHTML + JS + '</body></html>';

// Use the JavaScript methods to write to the iFrame, then close it
newIframe.contentWindow.document.open('text/html', 'replace');
newIframe.contentWindow.document.write(myContent);
newIframe.contentWindow.document.close();

Obviously key in there is the relevant CSS you want to be sandboxed to the iframe:

<link rel="stylesheet" href="http://www.domain.com/styles-to-be-sandboxed-to-iframe.css">

With that in place each pattern library entry can duplicate the copy & paste markup section into a sandboxed iframe to allow an ‘in-page’ rendering of the code snippet/pattern with sandboxed CSS.

For bonus points, you may want to set the height of the iframe to match the contents. Here’s how you could do that with jQuery (as an example):

$('#iFramedHTML').load(function () {
	$(this).height($(this).contents().find('body').height());
	$(this).width($(this).contents().find('body').width());
});

My latest book, 'Enduring CSS' is out now

Get $5 off HERE ↠

Write and maintain large scale modular CSS and embrace modern tooling including PostCSS, Stylelint and Gulp