- Basic (grandpa’s) frames
- Inline frames or
iframes
- Accessing the inner document
- Access via
window.frames
- Frames hierarchy
- Iframe
onload
event - HTML5
seamless
andsandbox
attributes
Frames is an old-school way to split a browser window in several zones, so called frames, where each frame behaves as a separate window.
Basic (grandpa’s) frames
The HTML for basic frames could look like this:
<HTML> <FRAMESET cols="20%, 80%"> <FRAME src="left.html"> <FRAME src="right.html"> </FRAMESET> </HTML>
The HTML document which as frameset
instead of body splits browser window in sections. In the example above, there are two of them.
The left one is 20% of width, it loads left.html
, the right one is 80% and loads right.html
.
The frameset
element can be nested and provides several ways to split the window: either vertically or horizontally. Frames are allowed to contain frames. So, the browser window may be split into cells the way you like.
Each frame loads separate document. Reloading or navigation of a frame does not affect other frames.
The basic frames are deprecated. The frameset
tag and it’s helper tags frame/noframes
are removed from the modern HTML5 standard.
Actually, basic frames are out of use by now. They are given here for historical reasons and completeness only. So, we’ll move forward to more advanced frames stuff which is really used.
Inline frames or iframes
Inline frames provide a way to embed another page as a rectangular subwindow. For instance, here is an inline frame with top of http://javascript.info:
<iframe src="http://javascript.info"></iframe>
In action:
Usually you’d also set width, height etc. Almost all properties can be assigned with CSS, with a minor exception of frameborder
.
Removing the native frameborder
To remove the border around the iframe in an IE-compatible way, it should be set as an attribute.
In the example below, the first frame is bordered by default, the second is unbordered using CSS, and the last one has frameborder="0"
which will work for IE (including IE9).
Check this example in IE to see that only the last way works.
<style> * { width: 100px; height:40px } </style> <ol> <li><iframe src="JavaScript:'content'"></iframe></li> <li><iframe src="JavaScript:'content'" style="border:0"></iframe></li> <li><iframe src="JavaScript:'content'" frameborder="0"></iframe></li> </ol>
So, one usually sets frameborder="0"
and applies custom border with CSS if needed.
Iframe src
property
As you noticed in the example above, the src
attribute may be either standard or JavaScript:...
. In the latter case, the code is executed and the result is used as content.
src
An iframe without src
attribute is wild and awry.
It leads to problems in older browsers. In newer IEs it has problems with HTTPs: iframe
without src
gives non-secure warnings on SSL-enabled page.
The empty src=""
won’t work, because it actually means to load the URL referenced by “”, that is the current page.
To create an empty iframe
which works well on IE HTTPs, one should use src="JavaScript:''"
syntax.
Also, the src
attribute, like most standard attributes is accessible as DOM property: iframe.src
, so the DOM creation syntax is perfectly valid:
var ifr = document.createElement('iframe') ifr.src = '/my/url' document.body.appendChild(ifr)
Accessing the inner document
An iframe
element is just a DOM element, like any other. The only difference is that there exists a related window object. It is referenced in contentWindow
property.
So, iframe.contentWindow.document
will be the inner document.
You can access it or modify from parent window if both iframe and the parent come from one domain/host/port (security limitations are discussed more in detail in the next sections).
In the example below, the function makeGreen
accesses the document
of the iframe
element and modifies it.
<iframe src="JavaScript:'content'" style="height:60px"></iframe> <script> function makeGreen() { var iframe = document.getElementsByTagName('iframe')[0] var doc = iframe.contentWindow.document doc.body.style.backgroundColor = 'green' } </script> <input type="button" onclick="makeGreen()" value="click me">
Any html page has the document.body
after is has finished loading.
Even the most invalid one.
Access via window.frames
There is a special property window.frames
which allows to access iframe window objects directly.
There are two forms of access:
window.frames[0]
- access by numberwindow.frames['iframeName'] - access by iframe
name
<iframe src="JavaScript:''" style="height:80px" name="iframeName"></iframe> <script> function check() { alert(frames[0] === frames['iframeName']) } </script> <input type="button" onclick="check()" value="click me!">
Try it, click on the button above. You’ll see that frames
can be accessed both by number and by name. Funny, but it works.
Iframe name
attribute in IE
The name
attribute contains the name of the corresponding window. It works seamlessly on all browsers excepts IE<8 (and IE8 compat mode).
In older IEs, there are quite a few bugs related to assigning name
in run-time, so the typical workaround is to create an iframe with name.
// IE proprietary createElement syntax allows attributes document.createElement('<iframe name="myiframe" src="JavaScript:\'\'">')
.. Or you can just use
innerHTML
.
Remember that as a mighty workaround for all name-related problems.
Frames hierarchy
A window has frames
collection to access the frames.
The frames, in their turn, has parent
property which refers to the enclosing window:
window.frames[0].parent === window // always true
Also, for the case when frames are nested, there is an easy way to get the topmost frame using the top
property.
// (assuming nested frames exist) window.frames[0].frames[0].frames[0].top === window
The top
property also gives an easy way to check if the page is inside a frame.
The example below shows alert in such case and forces the document to show in topmost frame by putting it’s URL into top.location
:
if (window !== top) { alert('The script is executed in frame!') top.location = window.location+'' }
Iframe onload
event
A window has onload
event which fires when it is loaded completely. But in case of iframe, there are two ways to catch onload:
- Assign the handler to iframe window, like
frames[0].onload = ...
- Assign the handler to iframe DOM element:
iframeElem.onload = ...
The difference is demonstrated in the example below:
<iframe src="http://google.com/" name="google" style="height:100px"></iframe> <script> // set onload on element document.getElementsByTagName('iframe')[0].onload = function() { alert('Frame element loaded') } // set onload on window frames[0].onload = function() { alert('Window loaded') } </script>
Run the example above. You’ll see that only the iframe
attribute works, because it doesn’t depend on cross-domain access policy like setting onload
on a window from another domain.
So, shortly, the iframe.onload
is more reliable then iframe.contentWindow.onload
.
HTML5 seamless
and sandbox
attributes
The seamless and sandbox attributes are new in HTML5.
At the time of writing (Jan 2011), the seamless
is not supported. It should integrate the iframe seamlessly into page by removing border and applying CSS styles of the parent as if the iframe were just an element.
The sandbox
is simpler to implement. It is supported by the recent Webkit (e.g in Chrome). When the sandbox
attribute is set, the iframe content is treated as being from a unique origin, forms and scripts are disabled, links are prevented from targeting other browsing contexts, and plugins are disabled.
So, the following iframe lives in a separate, very limited world. Check it using the latest Chrome:
<iframe sandbox src="/files/tutorial/window/sandboxed.html"></iframe>
The sandbox
attribute may contain space-delimited flags which relax the limitations:
- allow-same-origin
- Doesn’t force the unique origin for
iframe
contents. - allow-top-navigation
- Allows
iframe
to navigate parent context, e.g. changeparent.location
. - allow-forms
- Allows forms submissions from inside
iframe
. - allow-scripts
- Allows scripts execution. Still, scripts are not able to create popups.
The aim of sandboxing is to limit. It can’t lighten default limitation, like make an iframe from another domain to appear from the same origin.
All it can do is limiting, with possible exceptions, like:
<iframe sandbox="allow-same-origin allow-forms" src="do.php"></iframe>
The iframe above will have JavaScript disabled, but may remain in same origin and the forms may also be submitted.