srcdoc 必须是完整 html 文档,需包含 doctype、html、head、body 结构,内联 css/js 并转义引号,配合 sandbox 限制权限,动态更新会重载 iframe,ie 需降级 fallback。

srcdoc 必须是完整 HTML 文档,不是任意片段
直接写 srcdoc="<div>Hello</div>" 会导致 Safari 空白、Chrome 渲染异常、Firefox 行为不一致。浏览器把 srcdoc 值当作整个 HTML 文件解析,缺 、<code>、、 就不可靠。
正确结构必须显式包含:
(推荐,部分旧版 Safari 强制要求)<title>Preview</title>...-
<title></title>标签虽非强制,但缺失时某些 Safari 版本可能拒绝渲染 - 未闭合标签(如
<div>hello)会截断后续内容,导致预览不全 <h3>双引号、CSS 和 JS 必须内联且转义</h3> <p>你在 <code>srcdoc字符串里写的任何双引号(比如style="color:red"),都会和外层 HTML 属性的双引号冲突。不处理就会字符串截断,iframe 空白无报错。- 推荐用单引号包裹整个属性:
srcdoc='<div style="color:red">OK</div>' - 或对双引号实体转义:
srcdoc="<div style="color:red">OK</div>" -
<script src=""></script>和<link href="">在srcdoc中完全失效——外部资源一律不加载 - CSS 必须用
<style></style>内联;JS 放在底部,或包装在DOMContentLoaded回调里,避免操作未挂载节点
sandbox 是必选项,不是可选配置
没加
sandbox的srcdoc相当于裸奔:脚本可执行、表单可提交、window.open()可弹窗、甚至能尝试修改top.location。哪怕内容是你自己拼接生成,一旦含用户输入(比如富文本编辑器预览),XSS 风险就真实存在。- 最简安全起点:
sandbox=""—— 完全禁用脚本、表单、弹窗、存储访问 - 仅需展示静态内容:保留
sandbox="",不加任何allow-token - 需运行 JS(如按钮交互):
sandbox="allow-scripts",但绝不要加allow-same-origin,否则iframe.contentDocument可读取父页 DOM - 若需调用父页方法,只能用
window.parent.postMessage(),不能依赖直接引用
动态更新 srcdoc 会重载 iframe,JS 状态全丢
执行
iframe.srcdoc = newHtml看似简单,实则触发 iframe 全量重载:已绑定的事件监听器、定时器、console输出、正在执行的函数全部销毁。这不是“刷新页面”,而是销毁并重建整个浏览上下文。- 不要用
srcdoc做高频更新(如实时 Markdown 预览每键触发)—— 改用iframe.contentDocument.write() + document.close()更轻量(但需确保同源且无sandbox限制) - 若必须用
srcdoc更新,每次都要重新注入内联 JS,并靠postMessage同步状态 -
iframe.contentWindow无法持久保存变量,重载后该对象指向新窗口实例 - 调试时注意:控制台里看到的
console.log是旧上下文的残留输出,新脚本需重新打点
srcdoc,降级路径不是可选项。必须同时设src和srcdoc,让 IE 回退到src(比如指向一个静态 HTML 文件或data:text/html;base64),而现代浏览器优先使用srcdoc。复杂点在于:沙箱权限、文档结构完整性、动态更新时的状态同步,三者稍有疏漏,预览就变成 XSS 入口或空白画布。 - 推荐用单引号包裹整个属性:











