The iframe srcdoc Attribute

I was working on a web page generation program recently and was looking for a way to present different versions of the same page with slight differences in the markup and styles. Although using the iframe element came to mind I wasn't keen on rendering out lots of different versions of the page and then referencing them individually in each iframe. I did think about creating using an API to send back each page on request but I thought that this might just overcomplicate the program.

After a little bit of research I came across the srcdoc attribute of the iframe, which solved the problem quite neatly.

The iframe is normally used with a src attribute, which points to some external page. The following example will render the page at example.com within the page.

<iframe src="https://www.example.com/"></iframe>

Alternatively, it is possible to use the srcdoc attribute to directly embed HTML into the iframe as an inline page. The following example will render an iframe containing some HTML.

<iframe srcdoc="<p>Some HTML</p>"></iframe>

This can be used to maximum effect by just using the iframe and the srcdoc attribute to render an entire web page. This is an example of this in use with a page that contains some styles to produce a simple layout.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
</head>
<body>
  <iframe srcdoc='<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
</head>
<style type="text/css">
*{font-family:Verdana, Trebuchet, Lucida, Arial;padding:0;margin:0;}
div.sitemast {
font-size:large;
height:4rem;
}
div.menu{
float:left;
width: 25%;
}
div.menu ul{
list-style:none;
background:cyan;
}
div.menu li a{
padding-left:0.5rem;
}
div.menu li li a{
padding-left:1rem;
}
div.content{
float:right;
width: 75%;
background:yellow;
}
</style>
</head>
<body>
<div class="sitemast"><h1>Sitemast</h1></div>
<div class="menu"><ul><li><a href="\">Menu</a></li><li><a href="\">Menu</a><ul><li><a href="\">Sub Menu</a></li><li><a href="\">Sub Menu</a></li></li></ul></ul></div>
<div class="content">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet consectetuer tincidunt velit Donec orci vitae. Interdum quam lacinia augue quis sagittis sem ut tellus Curabitur at. Aliquam orci montes eu dis lorem penatibus hendrerit semper quis rhoncus. Ut sed felis elit Sed porttitor mauris wisi urna adipiscing quam. At sit augue congue volutpat et Phasellus.</p>
</div>
</body>
</html>'></iframe>
</body>
</html>

Note that I used single quotes for the srcdoc attribute. This helps render the page correctly as all of the double quotes would otherwise need to be escaped.

This works, but unfortunately the web page is rendered within the default size of the iframe, which is about 150px high and 300px wide. The rendered page is therefore squashed into the iframe boundaries. By adding some default styles to the page we can alter this and change not only the size but also the scale of the rendered page so that it fits within the iframe as it would in a full size browser window.

The following styles will increase the height and width of the iframe and reduce the scale of the contents of the iframe in all browsers.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
</head>
<style type="text/css">
  iframe {
      -ms-transform:scale(0.50);
      -moz-transform:scale(0.50);
      -o-transform: scale(0.50);
      -webkit-transform: scale(0.50);
      transform:scale(0.50);
      height: 500px;
      width: 1000px;
  }
</style>
<body>
  <iframe srcdoc='<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
</head>
<style type="text/css">
*{font-family:Verdana, Trebuchet, Lucida, Arial;padding:0;margin:0;}
div.sitemast {
font-size:large;
height:4rem;
}
div.menu{
float:left;
width: 25%;
}
div.menu ul{
list-style:none;
background:cyan;
}
div.menu li a{
padding-left:0.5rem;
}
div.menu li li a{
padding-left:1rem;
}
div.content{
float:right;
width: 75%;
background:yellow;
}
</style>
</head>
<body>
<div class="sitemast"><h1>Sitemast</h1></div>
<div class="menu"><ul><li><a href="\">Menu</a></li><li><a href="\">Menu</a><ul><li><a href="\">Sub Menu</a></li><li><a href="\">Sub Menu</a></li></li></ul></ul></div>
<div class="content">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet consectetuer tincidunt velit Donec orci vitae. Interdum quam lacinia augue quis sagittis sem ut tellus Curabitur at. Aliquam orci montes eu dis lorem penatibus hendrerit semper quis rhoncus. Ut sed felis elit Sed porttitor mauris wisi urna adipiscing quam. At sit augue congue volutpat et Phasellus.</p>
</div>
</body>
</html>'></iframe>
</body>
</html>

This produces the following output with the actual size of the page being reduced in size by 50%.

Rendering of a iframe

This gave me a handy way of displaying multiple iframes onto the same page and also allowing those inline pages to be scaled down so that they could be shown all at once.

I should note for completeness that this can also be done using the src attribute. To do this the attribute must start with the text "data:text/html,", which indices to the browser that the reset of the string should be rendered as HTML.

<iframe src="data:text/html,<p>Some HTML</p>"></iframe>

I have found this slightly more problematic to deal with when rendering pages inline, but it is possible. This also might be the best option if you are wanting to use Internet Explorer as that browser does not support the srcdoc attribute at all.

Comments

Thanks for this, it was very helpful in me getting a prototype working.

Permalink

Hi Phil,

I want to have a HTML5 box, like Iframe, to exhibit a dynamic list. Following your explanation, I have tried the following code, without success:

<iframe sandbox="allow-scripts" srcdoc="<div><ul>
                            @foreach (var item in Model.MessageList)
                            {
                                if (item.Cpo005 == Model.IdS)
                                {
                                    <li style="color:darkmagenta"><small>@Html.DisplayFor(modelItem => item.Cpo003) @Html.DisplayFor(modelItem => item.Cpo004) - @Html.DisplayFor(modelItem => item.Cpo007)</small></li>
                                }
                                else
                                {
                                    <li><small>@Html.DisplayFor(modelItem => item.Cpo005) @Html.DisplayFor(modelItem => item.Cpo006) - @Html.DisplayFor(modelItem => item.Cpo007)</small></li>

                                }
                            }
                            </ul></div>"></iframe>
                    <div>

My website is based on C# and Razor Pages. Is it possible?

Thanks in advanced.

Permalink

I don't know much about Razor pages, but you still need to have valid HTML in your response. You can see in your comment that the syntax highlighter doesn't really like the code entered because you have multiple " characters in the attribute.

Try changing the code from this:

<iframe sandbox="allow-scripts" srcdoc="..."></iframe>

To this:

<iframe sandbox="allow-scripts" srcdoc='...'></iframe>

With single quote marks. You may need to escape or encode non HTML valid characters in your srcdoc attribute as welll.

Name
Philip Norton
Permalink

Add new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
12 + 7 =
Solve this simple math problem and enter the result. E.g. for 1+3, enter 4.
This question is for testing whether or not you are a human visitor and to prevent automated spam submissions.