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

srcdoc 必须是完整 HTML 文档,不是任意片段
直接写 srcdoc="<div>Hello</div>" 会导致 Safari 空白、Chrome 渲染异常、Firefox 行为不一致。浏览器把 srcdoc 值当作整个 HTML 文件解析,缺 <!DOCTYPE html>、<html>、<head>、<body> 就不可靠。
正确结构必须显式包含:
-
<!DOCTYPE html>(推荐,部分旧版 Safari 强制要求) <html><head><title>Preview</title></head><body>...</body></html>-
<title>标签虽非强制,但缺失时某些 Safari 版本可能拒绝渲染 - 未闭合标签(如
<div>hello)会截断后续内容,导致预览不全
双引号、CSS 和 JS 必须内联且转义
你在 srcdoc 字符串里写的任何双引号(比如 style="color:red"),都会和外层 HTML 属性的双引号冲突。不处理就会字符串截断,iframe 空白无报错。
- 推荐用单引号包裹整个属性:
srcdoc='<div style="color:red">OK</div>' - 或对双引号实体转义:
srcdoc="<div style="color:red">OK</div>" -
<script src="">和<link href="">在srcdoc中完全失效——外部资源一律不加载 - CSS 必须用
<style>内联;JS 放在<body>底部,或包装在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 入口或空白画布。



















