HTML 预览

在受限沙箱中预览 HTML

正在加载工具…

关于 HTML 在线预览

HTML 预览器在编辑器旁边用沙箱框架渲染 HTML 片段,让你看到浏览器真实产出的结构与样式。从你粘贴的内容到最终渲染之间隔着两层:一层是移除危险标记的净化器,一层是没有授予任何权限的 iframe 沙箱。

预览是渲染辅助工具,不是安全工具。它回答「这段标记能不能产出我预期的排版」;隔离保护的是你正在看的这个页面,而不是为这段 HTML 出具可以对外提供的证明。这个区别很重要,因为限制本身也会改变你看到的东西:被净化器移除的元素不留痕迹,被沙箱拒绝的能力也不报错,只是悄无声息地失效。搞清楚是哪一层拿走了东西,通常是理解「预览不对劲」的最快路径。

如何使用这个开发者工具

  1. 把 HTML 片段粘贴到左侧面板。右侧框架随输入重新渲染,没有需要点击的按钮。
  2. 先看排版和字体,这是预览能忠实复现的部分。
  3. 发现缺东西时,先判断是哪一层拿走的:标记里整个消失的元素是净化器拿的;能渲染出来但点了没反应的控件,是被沙箱拦的。
  4. 把相对路径换成绝对 https 地址或 data URL,因为从内联源码渲染的框架,会把相对引用解析到本站地址上,而不是你的项目里。
  5. 所有涉及交互的内容都请挪回真正的开发服务器。脚本、表单和本地存储是否可用,这个预览给不出答案。

实例:什么能活着穿过净化器

这段片段里有四样人们常粘的东西:开头的 style 块、行内事件处理器、相对路径图片,以及一个 javascript: 链接。其中恰好只有一样完整抵达了框架。

输入
<style>
  body { font: 16px/1.5 system-ui; margin: 0; }
  .card { border: 1px solid #d0d7de; border-radius: 8px; padding: 16px; }
</style>
<div class="card">
  <h1 onclick="track()">Weekly report</h1>
  <img src="logo.png" alt="Logo">
  <p>Built <a href="javascript:void(0)">by hand</a>.</p>
</div>
真正进入框架的标记
<div class="card">
  <h1>Weekly report</h1>
  <img src="logo.png" alt="Logo">
  <p>Built <a>by hand</a>.</p>
</div>

style 块消失,是因为写在任何正文内容之前的 style 元素会被解析进文档头部,而最终只保留正文内容——把它挪到 div 之后就能留下。onclick 属性和 javascript: 链接地址被剥掉,只剩一个没有目标的 a 元素。img 标签活了下来,但 logo.png 会被解析到本站地址上,因此加载不出来。

两层各拦下什么,失效时长什么样

被净化器拿走的东西,在渲染之前就已经不在标记里了;被沙箱拒绝的能力仍留在标记中,只是用起来没有任何效果。

你写的内容被谁拦下表现
script 元素两层都拦不会执行,元素也不在框架里
onclick、onerror 等属性净化器照常渲染,永远没有反应
javascript: 开头的链接地址净化器链接没有跳转目标
iframe、object、embed净化器整块消失,连占位都没有
样式表 link 元素净化器外部 CSS 永不加载
meta 或 base 元素净化器无法设置 viewport、字符集或基准地址
带提交按钮的表单沙箱,没给 allow-forms渲染正常,点提交什么也不发生
指向其他页面的链接或弹窗沙箱点击没有可见效果
Cookie、localStorage 或同源请求沙箱,没给 allow-same-origin不透明源,访问存储会抛异常
写在第一个元素之后的 style 元素都不拦正常生效,这是加 CSS 的可靠办法
绝对 https 地址的图片或字体都不拦按普通子资源正常加载

常见问题排查

粘贴一整个页面,结果几乎什么都没渲染出来。

成因 标记会被当作文档重新解析,最终只保留正文内容。头部里的一切——标题、meta 标签、样式表链接,以及写在那里的 style 块——都被丢弃,body 元素自身的属性也随之丢失。

解决办法 只粘贴正文内容,并把 CSS 放进一个写在第一个元素之后的 style 元素里。如果页面依赖 body 标签上的某个 class,就用一个带该 class 的 div 把内容包起来。

用相对路径引用的 CSS 文件、图片或字体一直加载不出来。

成因 框架是从内联源码渲染的,它的基准地址就是本站当前页面地址。logo.png 或 /assets/app.css 这样的引用会解析到那个地址上,请求一个根本不存在的文件。base 元素也救不了,因为 base 元素会被移除。

解决办法 预览期间改用绝对 https 地址,或者把小体积资源内联成 data URL。标记放回项目里之后再换回相对路径,那时它们才能正确解析。

按钮渲染得好好的,点下去毫无反应。

成因 脚本被净化器移除了,就算留着也会被沙箱挡掉;表单提交同样需要框架没有被授予的权限。标记本身是完整的,缺的只是行为。

解决办法 行为请在本地开发服务器或浏览器开发者工具里验证。这个预览用来回答它能回答的部分:结构、间距、字体,以及布局如何重排。

预览看起来没问题,所以这段 HTML 应该是安全的。

成因 预览剥掉危险标记,是为了让你正在看的这个页面保持完好。那是对浏览者的防护,不是对文档的审计。

解决办法 把它当作纯粹的渲染辅助。不可信的 HTML 请用为你的应用配置好的真实净化库、内容安全策略和安全评审来把关。预览看着干净,并不能证明原始标记的任何性质。

适合用这个工具的场景

  • 不用起服务,就能检查邮件模板或静态片段的结构和间距。
  • 阅读别人发来的、或从数据库字段里捞出来的标记,同时不让它运行。
  • 用写在内容之后的 style 元素,对真实标记试一个小的 CSS 改动。
  • 确认脚本全部失效后片段长什么样,这大致就是纯文本阅读器或严格的邮件客户端会呈现的效果。

应该换用别的工具的场景

  • 测试应用。脚本、表单、存储和跳转都被有意禁用,请改用开发服务器。
  • 评估标记能否安全发布。沙箱保护的是这个页面而不是你的用户,而且这里不做任何漏洞检查。
  • 预览渲染后的 Markdown 文档。输入是 Markdown 时请用 Markdown 预览器,它会先完成转换。

隐私与数据处理

标记在当前浏览器标签页内完成净化和渲染,绝不上传。框架带的 sandbox 属性不授予任何权限,因此内容不执行脚本、不提交表单、不打开窗口、不做跳转,也无法访问 Cookie、存储或本站源。但绝对地址的图片和字体仍会被当作普通子资源请求,远端服务器能看到这次请求发生过。

相关开发者工具

常见问题

预览会执行 JavaScript 吗?

不会,而且有两道彼此独立的防线。script 元素在渲染前就被从标记里移除;框架创建时带的是空的 sandbox 属性,这会连同其他所有权限一起,拒绝脚本执行。

为什么图片能加载,样式表不行?

拦它们的不是同一样东西。绝对地址的图片属于普通子资源,正常加载。样式表通常靠 link 元素挂载,而 link 元素会被净化器移除,请求根本没发出去。在这里加 CSS 请用内联样式规则。

能测试页面在手机上的表现吗?

可以缩放窗口看布局重排,这覆盖了大部分响应式 CSS。做不到的是设置 viewport meta 标签,因为 meta 元素会被移除,所以任何依赖移动端视口缩放的效果都复现不了。

预览算安全扫描器吗?

不算。它把危险部分剥掉之后渲染标记,好让你能安全地看一眼。它不分析输入,不报告自己移除了什么,也不会对原始文档在其他场景下是否安全给出任何结论。

为什么第一个可见元素以上的内容全没了?

只有正文内容会被渲染。文档头部——包括标题、meta 标签、样式表链接和写在那里的 style 块——都会在净化过程中被丢弃,body 标签上写的属性也一样。

这里看到的效果和真实浏览器一致吗?

布局和样式来自你此刻正在使用的同一个渲染引擎,因此和这个浏览器高度一致。但它不会和另一个浏览器、邮件客户端或自带样式表的阅读器一致,而且框架本身还加了一点关于外边距和配色方案的重置。