在 <iframe> 中,srcdoc="..." 和 src="data:text/html,..." 有什么区别?

93

例如,这两者之间的区别是什么:

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

Demo

如果它们完全相同,为什么HTML5会添加srcdoc属性?

编辑

也许我表述不够清楚。我并不是将srcsrcdoc进行比较,而是使用文本/HTML数据URI的srcsrcdoc进行比较。

那么,如果功能图表如下:

                   |  src属性             |  srcdoc属性
 --------------------------------------------------------------------
  URL              |  是                 |  不使用src则为 否(*)
  HTML内容          |  是,使用数据URI      |  是

为什么需要srcdoc呢?


(*) 注意

似乎可以使用srcdoc通过URL(演示)加载页面,其中使用了具有src属性的子iframe:

<iframe srcdoc="<iframe src='http://microsoft.com'></iframe>"></iframe>
9个回答

66

其他答案列出了一些表面上的差别,但是实际上错过了解释“为什么”浏览器/规范编写者基本上会复制已经存在的内容的关键差别:

<iframe src="data:...untrusted content" sandbox /> <- 在现代浏览器中安全,对于不支持沙盒的旧浏览器来说是不安全

<iframe srcdoc="...untrusted content" sandbox /> <- 在现代浏览器中安全,对于旧浏览器来说是安全的(虽然不起作用)

这个新语法为内容作者提供了一种保护其用户的方法,即使他们可能正在使用旧的浏览器。如果没有它,内容作者将不愿使用沙盒功能,并且它将不会被使用。


如果主要的好处是不受信任的内容,为什么要将其规范化为内联内容 - 大多数不受信任的内容不是来自外部URL吗?即为什么不使用sandboxedsrc属性来接收[data] URI?(这也可以避免一些未来的浏览器在实现srcdoc时没有实现sandbox)。 - Beni Cherniavsky-Paskin
1
因为作者已经可以使用外部URL(在单独的域上)来提供不受信任的内容。 - Fabio Beltramini
“secure” 是什么意思?它无法访问嵌入页面吗?还是嵌入页面无法访问它?或者两者都不行?还是其他原因? - Gregory Magarshak
否则,这与普通的div或HTML组件有什么区别呢? - Gregory Magarshak
任何关于 iframe 的“沙盒”(sandbox)的文章都会讨论它提供了哪些好处。 - Fabio Beltramini

23

带有HTML内容的src属性的iframe跨域。即使使用data URLs,如此处所述,也是如此。

data: URL具有新的、空的安全上下文。

但是,带有HTML内容的srcdoc属性的iframe不会跨域

因此,如果您尝试从父页面访问/操作iframe,则使用src属性可能会导致错误

阻止了源为“…”的框架访问跨源框架。


3
这是一个很好的观点,Chrome将数据URI视为跨域。Firefox将它们视为同源,不确定Edge会怎么处理。 - Oriol
2
“not cross domain” 是什么意思? - Gregory Magarshak
2
@GregoryMagarshak所说的“非跨域”意味着iframe内容将被视为来自与父页面相同的域。因此,它不会受到浏览器同源策略的限制,该策略通常会阻止浏览器访问远程页面的内容,就像使用src ='some-url.com'时一样。https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy - johny why

23

来自MDN文档关于srcdoc属性

内联HTML嵌入,覆盖src属性。如果浏览器不支持srcdoc属性,则会回退到src属性中的URL。

旧版MDN文档关于srcdoc说:

嵌入上下文所包含的页面内容。预计此属性将与sandboxseamless属性一起使用。

因此,srcdoc属性将覆盖使用src属性嵌入的内容。

演示

(注意:seamless 属性已被删除, 另一个答案 描述了如何使用 sandbox 属性srcdoc 属性一起使用;这两个属性都是在 HTML5 中引入的;如果 srcdoc 包含不受信任的内容,则应该使用 sandbox 属性。


此外,关于以下代码片段data:text/html的内容,它被称为data URL它可能存在长度限制,因此src受到显示限制,而srcdoc则不受限制。

MSDN提到了length limitations:

Data URIs不能超过32,768个字符。

但其他浏览器可能会有different data URL length limits (higher limits) on data URLs themselves(例如Chromium可能允许512个URL),但仍然不允许URL超过2MB


因此,“srcdoc”属性将覆盖使用“src”属性嵌入的内容。但在Firefox 24中似乎不是这样,我看到两个IFrame中嵌入了Microsoft的网站。 - Marcel Korpel
2
@MrAlien 对于数据URI的长度限制,你提出了一个很好的观点。与HTML属性不同,它们没有限制。无论如何,似乎这个限制是由Microsoft实现所施加的,因为MDN没有提到任何限制,而RFC标准只是说“请注意,一些使用URL的应用程序可能会强制实施长度限制”。 - Oriol
@Oriol 谢谢,是的,MDN 没有指定任何限制,但我确定 URI 有限制。 - Mr. Alien
1
“srcdoc”之所以必要(正如此答案所暗示但未明确说明的那样)是因为data URIs不支持HTML内容的普遍性。这意味着,如果浏览器不支持在“src”中使用data URI,则没有优雅的回退方法来显示内容。然而,使用“srcdoc”并将http URI用于“src”,该URI解析为相同的嵌入式内容,确实为浏览器提供了优雅的降级选项。 - daiscog
3
那个数据URI限制是真的吗?HTMLCanvasElement.toDataURL经常返回大于32k的dataURLs。 - gman
显示剩余3条评论

15
截至撰写本文时,Chrome(v36)中的srcdoc允许设置和获取cookie,而使用data URL的src则不允许:

未捕获的SecurityError:无法从'Document'读取'cookie'属性:在'data:'URL中禁用了Cookie

这可能对您很重要,但排除了我正在构建的应用程序中使用data URL的可能性,这很遗憾,因为IE当前当然不支持srcdoc(v11)。

1
好的观点。在某些浏览器上,数据URI存在一些限制,因此在这些情况下,“srcdoc”效果更好。 - Oriol
在Chromium 81中,父框架的背景和字体样式也会层叠到iframe中,增加了更多的实用性。 - vhs

9

另一个显著的区别是,带有数据URI支持的src属性支持URI百分比编码规则,而srcdoc不支持,因为它支持常规的HTML语法。

这些来源将产生不同的结果:

<iframe srcdoc="<p>hello%20world</p><h1>give%0D%0Ame%0D%0Asome%24</h1>"></iframe>

<iframe src="data:text/html;charset=UTF-8,<p>hello%20datauri<p><h1>give%0D%0A me%0D%0Asome%24</h1>"></iframe>

我也注意到了属性值中js脚本解析的差异(可能不仅仅是百分号编码),但还没有找出规则…


1
src 的内容必须进行 URL 编码才能被正确处理。请参考这个问题了解如何进行编码。 - user
我在对较大的文本文件进行URI编码属性值时运气不太好。对我有效的方法是事先在bash中使用recode(1)对输入进行清理。 - vhs

1
另一个区别在于 iframe HTML 内部的片段链接是如何工作的。假设您的 HTML 内容有一个指向 文件片段/哈希/ID 的链接/<a>,该片段位于同一页内,如下所示:
<a href="#in_src"></a>

<!-- lots of other content, requiring scrolling -->

<p id="in_src"></p>
  • 如果你使用了src属性(jsfiddle示例jsbin),相同的链接将会滚动/跳转到相关片段(正如我所期望的一样)。

  • 如果你使用了srcdoc属性(jsfiddle示例jsbin),像上述的片段链接将会尝试重新导航整个iframe到一个全新的页面(基于父页面的上下文?我不确定,但这不是我期望的)。

可能是因为在srcdocsrc域名的差异导致的?也许是它们的baseURI值不同(请参见下文?)我不确定。

我在Chrome版本111.0.5563.149(官方版本)(64位)上进行了测试。

编辑

我想要链接可以滚动/跳转到文档片段,即使有srcdoc属性。所以在这个例子中,我使用JavaScript来...

  • addEventListener()添加点击事件
  • event.preventDefault()(防止锚点的iframe重置行为)
  • 使用location.hash= '#in_src';手动跳转到文档片段。
请注意,e.target.attributes.href.valuee.target.href的值不一定相同(即片段''#in_src'`的值)。
  • attributes.href.value 是 href 属性的字面字符串值,例如 '#in_src'
  • 但是 HTMLAnchorElement API 的 href 属性 是一个 "包含整个 URL的字符串 [值]"
    • 在使用 srcdoc 的情况下,href 值类似于 'https://...#i01'baseURI 值是父级 URL(iframeWindow.parent.document.baseURI),这可能是为什么单击链接会导航整个 iframe
    • 在使用数据 URI 的 src 的情况下,href 值类似于 'data:text/html,...#i01baseURI 值是数据 URI,并且将跳转到片段而不是导航整个页面)

-1
在您的示例中,这两种形式在功能上是相同的。但是,您可以同时使用srcsrcdoc属性,使非HTML5浏览器可以使用src版本,而HTML5浏览器可以使用srcdoc版本以及sandboxseamless属性,这些属性提供了更多的灵活性来处理iFrame。

但是 sandboxseamless 属性也可以与 src 属性一起使用,不是吗?在我看来,srcsrcdoc 更灵活。 - Oriol
@Oriol,我认为我的回答直接说明了为什么这很重要,而不是作为一个缺陷,而是作为一个特性。 - Fabio Beltramini

-4
主要区别在于'src'属性包含要嵌入iframe标记的文档地址。
另一方面,'srcdoc'属性包含要在内联框架中显示的页面的HTML内容。
'srcdoc'的主要缺点是不是所有浏览器都支持,而'src'与所有浏览器兼容。
有关详细说明,请查看以下链接: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe

9
但是 src 属性也可以包含页面的 HTML 内容,使用数据 URI。 - Oriol

-4

srcdoc:嵌入上下文所包含的页面内容。此属性预计与sandbox和seamless属性一起使用。如果浏览器支持srcdoc属性,则它将覆盖src属性中指定的内容(如果存在)。如果浏览器不支持srcdoc属性,则它将显示src属性中指定的文件(如果存在)。

src:要嵌入的页面的URL。


9
但是 src 属性也可以包含页面的 HTML 内容,使用数据 URI。 - Oriol

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接