srcdoc渲染富文本预览必须拼完整html文档结构,即包含preview...,否则浏览器解析异常导致空白或样式错乱。

srcdoc 渲染富文本预览必须拼完整 HTML 文档结构
直接把富文本 HTML 字符串(比如 <p>Hello</p>
<strong>World</strong>)塞进 srcdoc 属性,大概率空白或渲染异常。浏览器把 srcdoc 当作整个 HTML 文件源码解析,不是片段插入。
常见错误现象:Safari 完全不显示、Chrome 偶尔能渲染但样式错乱、控制台无报错却看不到内容。
- ✅ 正确结构必须包含:
<title>Preview</title>... -
<title></title>虽非强制,但旧版 Safari 缺失时可能拒绝渲染 - 富文本中若含内联样式(如
style="color:red"),外层srcdoc属性推荐用单引号包裹,避免双引号冲突 - 未闭合标签(如
<div>test)会导致后续内容被丢弃,预览截断 <h3>富文本里带 script 或 onclick?默认被 sandbox 拦住</h3> <p>哪怕你拼好了完整文档,只要没配 <code>sandbox,富文本里的<script>alert(1)</script>或<button onclick="foo()"></button>就能执行——这是 XSS 高危路径。但加了
sandbox=""后,这些脚本和内联事件全部静默失效,控制台也不报错,只当不存在。- 需要运行 JS(比如按钮计数、折叠展开)?只能用
sandbox="allow-scripts",且不能加allow-same-origin -
onclick、javascript:void(0)、eval()等内联行为,即使开了allow-scripts也默认被拦截——这是浏览器强制策略,不是配置漏了 - 想交互?得把逻辑写进
<script></script>标签里,并放在底部或DOMContentLoaded回调中 - 富文本若来自用户输入,绝不能信任其内容;JS 里操作 DOM 前务必检查节点是否存在
动态更新富文本预览会重载整个 iframe 上下文
每次执行
iframe.srcdoc = newHtmlString,等价于刷新 iframe:所有已绑定的事件监听器、定时器、正在执行的函数、console.log输出全丢,window和document引用全部失效。这不是“局部刷新”,是销毁重建一个全新浏览上下文。
- 高频更新(如每敲一个字就预览)别用
srcdoc赋值,性能差且状态无法保留 - 若需保留状态(比如表单输入未提交),改用
iframe.contentDocument.write(htmlString)+document.close(),但要求同源且无sandbox或至少含allow-same-origin(有安全风险) - 更稳妥方案:用
Blob URL替代,每次生成新blob:地址,确保完全隔离、无残留变量 - 注意内存泄漏:用完
URL.createObjectURL(blob)后,记得在iframe.onload里调用URL.revokeObjectURL(url)
IE 不支持 srcdoc,降级 fallback 必须显式提供
IE(包括 IE11)完全忽略
srcdoc属性,既不报错也不尝试 fallback,结果就是 iframe 显示为空白。不能靠“用户不用 IE”回避——企业内网、老旧系统仍大量存在。
- 必须同时设置
src和srcdoc:<iframe src="fallback.html" srcdoc="<!DOCTYPE..."></iframe> - 现代浏览器优先使用
srcdoc,IE 自动回退到src指向的静态 HTML 文件 - 用
data:text/html;base64,...做 fallback 也可行,但注意 URL 长度限制(部分浏览器上限约 2MB) - 若富文本含中文或特殊字符,
data:URL 必须做 UTF-8 编码 + base64,否则乱码
富文本预览真正难的不是拼字符串,而是平衡隔离性、交互性和兼容性。最容易被忽略的是:每次
srcdoc更新都是一次上下文重启,你以为只是换了个 div,其实连window对象都换了。 - 需要运行 JS(比如按钮计数、折叠展开)?只能用











