Embedding Content (iframe, embed, object)
Embed external content, videos, maps, and third-party widgets. Learn iframe security, sandbox attributes, and best practices for safe content embedding.
The <iframe> Element
<iframe> (inline frame) embeds another HTML page within the current page.
<iframe src="https://example.com"
width="800"
height="600"
title="Example website">
</iframe>Common Use Cases
1. Embedding YouTube Videos
<iframe width="560" height="315"
src="https://www.youtube.com/embed/VIDEO_ID"
title="YouTube video player"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>2. Embedding Google Maps
<iframe
src="https://www.google.com/maps/embed?pb=..."
width="600"
height="450"
style="border:0;"
allowfullscreen=""
loading="lazy"
referrerpolicy="no-referrer-when-downgrade">
</iframe>3. Embedding Social Media
<!-- Twitter embed -->
<iframe src="https://platform.twitter.com/embed/..."
width="550"
height="400">
</iframe>
<!-- Instagram embed -->
<iframe src="https://www.instagram.com/p/.../embed"
width="400"
height="480"
frameborder="0">
</iframe>Iframe Attributes
Essential Attributes
src- URL of the embedded pagewidth,height- Dimensions (pixels or %)title- Accessibility label (required!)name- Name for targeting with linksloading- lazy, eager (loading strategy)
Legacy Attributes (Avoid)
<!-- ⌠Deprecated attributes (use CSS instead) -->
<iframe frameborder="0" <!-- Use CSS: border: none -->
marginwidth="0" <!-- Use CSS: padding -->
marginheight="0" <!-- Use CSS: padding -->
scrolling="no"> <!-- Use CSS: overflow: hidden -->
</iframe>Security: The sandbox Attribute
The sandbox attribute restricts what the embedded content can do.
<!-- Fully sandboxed (most restrictive) -->
<iframe src="untrusted.html" sandbox></iframe>
<!-- Allow specific features -->
<iframe src="content.html"
sandbox="allow-scripts allow-same-origin allow-forms">
</iframe>Sandbox Permissions
| Permission | Allows |
|---|---|
allow-forms | Form submission |
allow-scripts | JavaScript execution |
allow-same-origin | Access to same origin (cookies, storage) |
allow-popups | window.open(), target="_blank" |
allow-top-navigation | Navigate top-level window |
allow-modals | alert(), confirm(), prompt() |
allow-scripts andallow-same-origin together for untrusted content - the iframe can remove its own sandbox!The allow Attribute (Feature Policy)
Controls what browser features the embedded content can access.
<iframe src="https://example.com"
allow="camera; microphone; geolocation; payment">
</iframe>
<!-- Deny all features except specified -->
<iframe src="https://example.com"
allow="camera 'none'; microphone 'none'">
</iframe>Common Features
camera- Access cameramicrophone- Access microphonegeolocation- Get user locationpayment- Payment Request APIautoplay- Autoplay mediafullscreen- Fullscreen APIencrypted-media- DRM protected content
Responsive Iframes
Make iframes scale with their container (16:9 aspect ratio):
<div class="iframe-container">
<iframe src="https://www.youtube.com/embed/VIDEO_ID"
title="Video"
allowfullscreen>
</iframe>
</div>
<style>
.iframe-container {
position: relative;
width: 100%;
padding-bottom: 56.25%; /* 16:9 aspect ratio (9/16 = 0.5625) */
height: 0;
overflow: hidden;
}
.iframe-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
/* 4:3 aspect ratio */
.aspect-4-3 {
padding-bottom: 75%; /* 3/4 = 0.75 */
}
/* 1:1 aspect ratio (square) */
.aspect-1-1 {
padding-bottom: 100%;
}
</style>Lazy Loading Iframes
<!-- Defer loading until near viewport -->
<iframe src="https://example.com"
loading="lazy"
title="Example">
</iframe>
<!-- Load immediately (default) -->
<iframe src="https://example.com"
loading="eager"
title="Example">
</iframe>Benefits: Faster initial page load, reduced bandwidth, better performance.
Communication Between Pages
postMessage API
<iframe id="myFrame" src="child.html"></iframe>
<script>
const iframe = document.getElementById('myFrame');
// Send message to iframe
iframe.contentWindow.postMessage('Hello from parent', '*');
// Receive messages from iframe
window.addEventListener('message', (event) => {
// Verify origin for security!
if (event.origin !== 'https://trusted-domain.com') return;
console.log('Received:', event.data);
});
</script><script>
// Receive messages from parent
window.addEventListener('message', (event) => {
// Verify origin!
if (event.origin !== 'https://parent-domain.com') return;
console.log('Received:', event.data);
// Send response back
event.source.postMessage('Hello from iframe', event.origin);
});
// Send message to parent
window.parent.postMessage('Message to parent', '*');
</script>SEO & Accessibility
✅ Best Practices
<iframe src="content.html"
width="800"
height="600"
title="Descriptive title of iframe content"
loading="lazy">
<!-- Fallback content for browsers without iframe support -->
<p>Your browser does not support iframes.
<a href="content.html">View content directly</a>.
</p>
</iframe>SEO Considerations
- Search engines may not index iframe content
- Use iframes sparingly for important content
- Provide alternative text/links
- Ensure iframe content is also accessible directly
The <embed> Element
<embed> embeds external content (PDFs, Flash, plugins). Mostly legacy now.
<!-- Embed PDF -->
<embed src="document.pdf"
type="application/pdf"
width="800"
height="600">
<!-- Better: Use iframe for PDFs -->
<iframe src="document.pdf" width="800" height="600"></iframe>
<!-- Or object with fallback -->
<object data="document.pdf" type="application/pdf" width="800" height="600">
<p>PDF cannot be displayed. <a href="document.pdf">Download PDF</a>.</p>
</object>The <object> Element
<object> embeds external resources with fallback support.
<!-- SVG with fallback -->
<object data="image.svg" type="image/svg+xml" width="300" height="200">
<img src="fallback.png" alt="Fallback image">
</object>
<!-- PDF with fallback -->
<object data="document.pdf" type="application/pdf" width="800" height="600">
<p>PDF viewer not available.
<a href="document.pdf">Download PDF</a>
</p>
</object>Security Best Practices
✅ Do:
- Always include
titleattribute - Use
sandboxfor untrusted content - Verify origins in postMessage handlers
- Use HTTPS for iframe sources
- Set appropriate CSP headers
- Use
loading="lazy"for below-the-fold iframes - Limit permissions with
allowattribute
⌠Don't:
- Embed untrusted content without sandbox
- Use both allow-scripts and allow-same-origin on untrusted content
- Trust postMessage data without origin verification
- Embed sensitive information in public iframes
- Forget accessibility (title attribute)
- Use iframes for primary content navigation
Common Issues & Solutions
Issue: "X-Frame-Options" Blocks Embedding
<!-- Error: Some sites prevent embedding -->
<iframe src="https://example.com"></iframe>
<!-- Error: Refused to display in a frame because it set 'X-Frame-Options' to 'deny'. -->Solution: You cannot embed sites that set X-Frame-Options. Use their official embed code or API.
Issue: Mixed Content
<!-- HTTPS page embedding HTTP iframe -->
<iframe src="http://example.com"></iframe>
<!-- Blocked: Mixed content -->Solution: Use HTTPS for iframe source, or load page over HTTP (not recommended).
Issue: Iframe Not Responsive
Solution: Use aspect ratio container trick (shown earlier).
Performance Optimization
- Use
loading="lazy"for below-the-fold iframes - Defer iframe loading until needed (add src with JavaScript)
- Minimize number of iframes (each is a full page load)
- Consider thumbnail/placeholder with click-to-load
- Use facades for heavy embeds (YouTube, etc.)
YouTube Lite Embed (Facade Pattern)
<div class="youtube-facade" data-video-id="VIDEO_ID">
<img src="https://i.ytimg.com/vi/VIDEO_ID/hqdefault.jpg" alt="Video thumbnail">
<button class="play-button">Play</button>
</div>
<script>
document.querySelectorAll('.youtube-facade').forEach(el => {
el.addEventListener('click', () => {
const videoId = el.dataset.videoId;
const iframe = document.createElement('iframe');
iframe.src = `https://www.youtube.com/embed/${videoId}?autoplay=1`;
iframe.allow = 'autoplay; encrypted-media';
iframe.allowFullscreen = true;
el.replaceWith(iframe);
});
});
</script>Complete Example: Secure Embed
<div class="video-container">
<iframe
src="https://www.youtube.com/embed/VIDEO_ID"
title="Tutorial video about HTML iframes"
width="560"
height="315"
frameborder="0"
loading="lazy"
sandbox="allow-scripts allow-same-origin allow-presentation"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
referrerpolicy="no-referrer-when-downgrade">
</iframe>
</div>
<style>
.video-container {
position: relative;
width: 100%;
max-width: 800px;
margin: 0 auto;
padding-bottom: 56.25%;
height: 0;
}
.video-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border: 0;
}
</style>