HTML iframe Table

PieceWhat it doesField note
<iframe>Embeds another documentEvery iframe is a full browsing context - weight accordingly
srcThe embedded URLsrcdoc embeds literal HTML instead - handy for sandboxed demos
titleAccessible nameThe one attribute screen readers require; "iframe" is not a name
loading="lazy"Defer offscreen loadsNew default-worthy attribute - saves real bandwidth on long pages
sandboxCapability jailEmpty = maximum restrictions; add back only what the embed needs
allowPermissions policyCamera, fullscreen, clipboard - per-frame grants
referrerpolicyReferer controlno-referrer for privacy-sensitive embeds
width / heightFrame sizeSet both + CSS aspect-ratio to stop layout shift (CLS)
frameborder (legacy)Border toggleDeprecated - use CSS border: 0
srcdocInline HTML documentPairs with sandbox for zero-network demos
cspEmbedded CSPExperimental per-frame content-security-policy
fetchpriorityLoad priority hinthigh for the map embed users came for, low for the rest
Reference: the MDN iframe reference. Three rules cover most embeds: every iframe gets a title (the accessibility failure every audit finds), every iframe gets explicit width and height (third-party embeds are the classic CLS source - reserve the box with aspect-ratio), and every third-party iframe gets loading="lazy" plus the smallest sandbox that still works. Bottom line: an iframe loads an entire second web page - treat each one like an image import you have to justify. Related tools: web vitals table (CLS economics), HTML attributes table, and HTML media table for first-party media that should not be an iframe at all.

An iframe loads an entire second web page inside yours - full browsing context, own JavaScript, own cookies, own network cost. That is its power and its price. The table below is the working twelve: the attributes that control what an embedded page can do, how eagerly it loads, and how much it disturbs the page around it.

Bottom line: three attributes cover most real deployments. title, because every accessibility audit finds iframes without one; loading="lazy" plus explicit width and height, because third-party embeds are the classic layout-shift source - reserve the box with CSS aspect-ratio and the page stops jumping; and sandbox with the smallest capability list that still works, because a compromised ad script should not inherit your origin's powers.

The honest part: the sandbox attribute is a jail with doors you open one by one. An empty sandbox allows almost nothing - scripts off, forms off, same-origin off - and each token you add (allow-scripts, allow-forms, allow-same-origin) grants a capability back. The dangerous combination is allow-scripts together with allow-same-origin on same-origin content: the embedded page can then remove its own sandbox. Pair the sandbox with srcdoc for zero-network demos and the jail stays sealed.

How to use

  1. Start the embed with the four defaults: src, title, width/height with CSS aspect-ratio, loading="lazy".
  2. Add capability attributes only as the embed proves it needs them: sandbox tokens, allow for fullscreen or clipboard, referrerpolicy for privacy.
  3. Audit the cost: every iframe is a second document - defer offscreen ones, and prefer first-party media elements over embed players when the content is yours.

Frequently asked questions

Why does every iframe need a title attribute?

Because assistive technology announces the frame by it: a screen reader user tabbing into an untitled iframe hears "frame" - no name, no purpose, no way to decide whether to enter. title is the iframe's accessible name (the same pattern as labeling a form input), and it is the single most common iframe failure in accessibility audits. Map embeds want title="Map of the store location"; payment frames want title="Payment form" - say what the frame contains, not what it is.

How does the sandbox attribute actually work?

It applies a default-deny policy: with no values, the embedded page cannot run scripts, submit forms, navigate the top page, or use plugins, and it is treated as a unique origin. Each token grants one capability back: allow-scripts (run JavaScript), allow-forms, allow-popups, allow-same-origin (keep its real origin for cookies and storage). The one combination to never ship with same-origin content is allow-scripts plus allow-same-origin - the framed page can then rewrite its own sandbox attribute, un-jailing itself. Third-party embeds ship with whatever token list their docs specify; your job is to not add more.

Do iframes slow down the page even when lazy?

loading="lazy" removes the network and render cost for frames below the fold - the browser skips them until they scroll near. What remains: the iframe element itself is cheap, but each frame that does load parses a full document with its own CSS and JavaScript, on the main thread of its own context. Maps, video players and social widgets are the usual heavyweights - lazy-load all of them, measure with the performance panel, and replace first-party content with native elements (a real <video> beats an embedded player for weight every time).

How do I stop an embed from shifting my layout?

Reserve the box before the frame loads: set width and height attributes (the intrinsic size), then CSS like aspect-ratio: 16 / 9 with width: 100% keeps the space stable at every screen size. The layout shift happens when the browser does not know the size until the embed's own document loads - which is always, for third parties. This is not cosmetic: layout shift is a Core Web Vitals metric, and unexpected movement from ads and embeds is the single largest CLS contributor on the average page.

Related tools