Topic 5.5
Iframes and Embeds
In one line
An <iframe> shows another web page inside yours, such as a map or a video; title, sandbox, allow and referrerpolicy make it accessible and safe, and server headers stop other sites from framing yours.
Think of it like this
A window in your house that looks into the neighbour's shop. You can see their shop and even talk through the window, but it's still their shop: you can't rearrange their shelves, and they can't walk into your kitchen. An <iframe> is that window. And just as you'd put a lock on a window, sandbox decides what the page behind it may do.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- iframe
- An element that shows another complete web page inside a rectangle on your page.
- Embed
- A piece of another service (a map, video, post) shown inside your page, usually with an iframe.
- Origin
- The protocol, domain and port of a page, like
https://hectal.in. Pages from different origins are kept apart. - Same-origin policy
- The browser rule that scripts from one origin can't read pages from another origin.
- sandbox
- An iframe attribute that turns off risky abilities (scripts, forms, popups) unless you allow them back.
- Permissions Policy
- Rules saying which browser features (camera, fullscreen, autoplay) a page or frame may use. Set on iframes with
allow. - Referrer
- The address of the page you came from, sent to the next site in the
Refererheader. - Clickjacking
- Tricking someone into clicking something on a hidden, framed copy of a site.
- postMessage
- A safe way for a page and an iframe from different origins to send each other messages.
Step by step
01Embed a map
Map services give you an embed snippet (in Google Maps: Share → Embed a map). Paste it, then fix what they leave out: a meaningful title, lazy loading and a responsive size.
<iframe src="https://www.google.com/maps/embed?pb=…"
title="Map showing our office in Pune"
width="600" height="450" style="border:0"
loading="lazy" referrerpolicy="no-referrer-when-downgrade"
allowfullscreen></iframe>02Embed a video
Video sites give a snippet with an allow list. Each item is a feature the player needs: autoplay, encrypted-media (protected video), picture-in-picture, and fullscreen through allowfullscreen. Keep the referrerpolicy they give you: some players need to know which site is embedding them.
<iframe width="560" height="315"
src="https://www.youtube-nocookie.com/embed/VIDEO_ID"
title="How the browser renders a page (video)"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen></iframe>03Make it responsive
The width and height attributes give the shape. In CSS, make the frame fill its container and keep the shape with aspect-ratio.
iframe {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
border: 0;
}04Sandbox content you don't trust
For user-written HTML or a third-party widget, start from an empty sandbox and add only what's needed. Here the widget may run scripts and open links in new tabs, but can't submit forms or navigate your page.
<iframe src="https://widgets.example.com/poll/42"
title="Reader poll"
sandbox="allow-scripts allow-popups"
width="400" height="300"></iframe>05Talk across the frame with postMessage
The framed page sends a message; your page listens and checks who sent it (event.origin) before trusting it.
window.addEventListener("message", (event) => {
if (event.origin !== "https://widgets.example.com") return; // ignore strangers
console.log("Poll result:", event.data);
});06Protect your own site from being framed
Set these response headers on your server (or hosting config). Test it: make a page on another origin that frames your site. The browser should refuse and print an error in the console.
Content-Security-Policy: frame-ancestors 'self'
X-Frame-Options: SAMEORIGINTry it yourself
- 1
Unlock frame B
In the first example, predict what changes if you write
sandbox="allow-scripts"on frame B. Run it: now both messages arrive. - 2
Remove the sandbox
In the second example, delete the whole
sandboxattribute and run it. Predict the last line. (Here the preview itself is sandboxed, so the frame stays separate; on a normal page asrcdocframe withoutsandboxshares the parent's origin and the answer would betrue.) - 3
Check a site's framing rules
Open any site, DevTools → Network, click the first (document) request and look at the Response Headers for
content-security-policywithframe-ancestors, orx-frame-options. Which of your favourite sites can be framed?
Code & diagrams
Both frames contain the same kind of script. Only the one with `allow-scripts` can run it.
Preview
Console
Nothing logged yet.Expected console output
Message: Hello from frame A
Done waiting. Frame B never spoke.The sandboxed frame gets an opaque origin, so even the page that made it can't read inside: the same-origin policy at work.
Preview
Console
Nothing logged yet.Expected console output
title: Reader poll
sandbox tokens: [ 'allow-scripts', 'allow-popups' ]
allows forms? false
allow: fullscreen; camera 'none'
referrerPolicy: no-referrer | loading: lazy
Can this page read the frame's document? false<!-- A map: give it a real title and lazy-load it -->
<iframe src="https://www.openstreetmap.org/export/embed.html?bbox=73.84,18.50,73.87,18.53&layer=mapnik"
title="Map of central Pune" width="600" height="400" loading="lazy" style="border:0"></iframe>
<!-- A video player -->
<iframe src="https://www.youtube-nocookie.com/embed/VIDEO_ID"
title="Course introduction video" width="560" height="315" loading="lazy"
allow="autoplay; encrypted-media; picture-in-picture" allowfullscreen
referrerpolicy="strict-origin-when-cross-origin"></iframe>Break it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Frame a site that forbids it
Write <iframe src="https://www.google.com" title="Google"></iframe> on your page.
Break #2
Forget the title
Embed a video with no title attribute.
Myth vs fact
Myth
Iframes are old and should never be used.
Fact
Framesets (<frameset>) are obsolete. Iframes are the standard, secure way to embed maps, video players, payment fields and untrusted content.
Myth
My JavaScript can read anything inside an iframe on my page.
Fact
Only if the frame has the same origin as your page. Cross-origin frames are sealed off by the same-origin policy; use postMessage to communicate.
Myth
sandbox="allow-scripts allow-same-origin" is safe for my own pages.
Fact
For same-origin content, that pair lets the framed script remove its own sandbox. Browsers even warn about it in the console.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Each cross-origin iframe in Chromium may run in its own renderer process (Site Isolation), which protects against Spectre-style memory attacks but costs memory. Many embeds on one page add up quickly.
- ▸
Heavy third-party embeds (a YouTube iframe pulls in several hundred kilobytes of JavaScript) are often replaced with a facade: a static thumbnail with a play button that swaps in the real iframe on click.
- ▸
loading="lazy"on iframes reached all major browsers in 2023 (Baseline 2023). Like images, don't lazy-load a frame in the first viewport. - ▸
frame-ancestorsin CSP replacesX-Frame-Optionsand supports lists of allowed origins (frame-ancestors 'self' https://partner.example). When both are present, browsers that support CSP useframe-ancestors. Note it only works as a header, not in a<meta>tag.
Remember this
- 1
An iframe (inline frame) is an element that loads a whole separate web page in a rectangle of your page:
<iframe src="https://www.example.com/widget" title="Weather widget" width="400" height="300"></iframe>. The framed page has its own HTML, CSS, JavaScript and history. Video players, maps, payment forms, social posts and ads are usually iframes. **srcdoc** puts the HTML of the inner page directly in an attribute instead of loading a URL (Hectal's live previews work this way). - 2
The browser keeps the two pages apart with the same-origin policy. An origin is the protocol + domain + port of a page (
https://hectal.inis one origin;https://www.youtube.comis another). JavaScript in one origin can't read or change a page from another origin, so your scripts can't peek into a framed bank page, and the framed page can't read yours. The two can still talk safely by sending messages withpostMessage. - 3
**
title** is required for accessibility: screen readers announce it so users know what the frame contains before entering it ("Map of our office", not "iframe"). Also setwidthandheight(or CSS size) so the page doesn't shift, and **loading="lazy"** for frames below the fold, since an iframe loads a whole page and is expensive. - 4
**
sandbox** locks the frame down. An emptysandboxattribute applies every restriction: no scripts, no forms, no popups, no navigating your page, and the content is treated as a unique opaque origin (a nameless origin equal to nothing, so it can't use its own cookies or storage). You then add back only what you need with tokens such asallow-scripts,allow-forms,allow-popupsandallow-same-origin. **Never combineallow-scriptsandallow-same-originfor content from your own origin**: the framed script could reach up and delete the sandbox attribute. - 5
**
allowsets the frame's Permissions Policy**: which powerful browser features it may use, such asfullscreen,autoplay,camera,microphone,geolocationorclipboard-write. Features not allowed are blocked inside the frame even if the framed site asks. **referrerpolicy** controls how much of your page's URL is sent to the framed site in theRefererheader; the browser default isstrict-origin-when-cross-origin(only your origin, likehttps://hectal.in/, is sent to other sites). - 6
The danger can also go the other way. Clickjacking is an attack where a malicious site loads your site in an invisible iframe and places it over a harmless-looking button, so a user who thinks they're clicking "Play" actually clicks "Delete account" on your site. The defence is on your server: send
Content-Security-Policy: frame-ancestors 'self'(only your own pages may frame you;'none'means nobody) and, for older browsers,X-Frame-Options: DENYorSAMEORIGIN. Then browsers refuse to show your page inside other sites.
Explain it without notes
What is the same-origin policy and how does it affect iframes?
What does an empty sandbox attribute block, and how do you add capabilities back?
What is clickjacking and how does a site defend against it?
What do allow and referrerpolicy control on an iframe?
Practice
Embed https://www.openstreetmap.org/export/embed.html?bbox=0,51.4,0.1,51.5 as an accessible, lazy, borderless 600×400 map.
Embed an untrusted widget from https://widget.example.com so that it can run scripts but cannot submit forms, open popups or navigate your page, and sends no referrer.
Write the response headers that stop every site, including yours, from framing your pages.
Trade-offs
- ↔
Embeds are quick to add and someone else maintains them, but they add weight, third-party cookies and tracking, and you can't control their look or uptime. A link or a static image is lighter when interaction isn't needed.
- ↔
A strict
sandboxis safest but may break a widget; add tokens one at a time and test, instead of starting permissive.
Done when you can
I can embed a map or video with an iframe and a descriptive
title.I can lock a frame down with
sandboxand add only the tokens it needs.I can set
allowandreferrerpolicyand say what they do.I can explain the same-origin policy and use
postMessagesafely.I can explain clickjacking and set
frame-ancestors/X-Frame-Options.