搜索结果预览工具

把标题、描述、网址三段粘进来,按 Google 桌面搜索结果的像素宽度口径(标题 600px、描述 920px × 2 行、网址行 480px)本地推算截断位置。不会访问你填的网址——可以在开发者工具 Network 面板自查,全程零请求。

按 20px 字号估算,标题 653px 超 600px 上限 53px,将被截断;描述 1531px 在两行 1840px 预算内,完整显示。

liuquan.net › jisuanqi › ludiandianjisuanqi
露点计算器_气温与相对湿度换算露点温度含简化公已截断
liuquan.net › jisuanqi › ludiandianjisuanqi
输入气温与相对湿度,用 Magnus-Tetens 公式(a=17.625,b=243.12)算出露点温度,同时给出简化式差值与 12 行对照表,可导出 CSV。全程本地计算,零网络请求。完整显示
标题估宽 / 上限653 / 600 px
描述估宽 / 上限1531 / 1840 px
网址行估宽 / 上限379 / 480 px
网址显示形态已去 https:// 与 www.

宽度估算用页面内建的字符宽度表(font-size 20px):汉字 20px、大写与数字 13.3px、小写 11px、空格 5.6px、窄字符 6px。这是可解释的近似模型,不是抄渲染引擎;真实字距由浏览器字体与 hinting 决定。

使用方法

  1. 把页面 <title> 粘进第一个框(上限 200 字符(示例已预填一段会被截断的标题)。
  2. 把元描述粘进第二个框(上限 500 字符)。
  3. 把网址粘进第三个框(上限 2048 字符)。只解析不访问——非 http / https 开头的会直接拒绝。
  4. 三个框都是多行文本框,Enter 是换行,要生成预览请按 Ctrl+Enter(Mac 是 Cmd+Enter)。
  5. 预览区会显示还原后的搜索结果样子,每段后面挂一枚徽标:黄色「已截断」表示超过该段的像素上限,绿色「完整显示」表示没超。结果区下方的进度条按标题的占用比例填充。

这个搜索结果预览工具能解决什么问题

一是写完标题才发现被砍掉半截。中文站常见的说法是「标题 30 个字符以内」,但 SERP 是按像素宽度截断的:同样 30 个字符,纯汉字是 600px(刚好到边),而如果混了大量英文与数字,30 个字符可能只有 400px(还留了 200px 空白)。决定因素是汉字占比,不是字符数——这正是本页把宽度算出来而不是数字数出来的原因。

二是判断描述会不会只显示一行。描述的预算是两行 × 920px = 1840px。纯中文时每行 46 个汉字、两行 92 个;换成纯小写英文则是每行约 84 个字符、两行约 167 个。同一段文案,中文版和英文版的有效长度完全不同。

三是核对网址在结果里长什么样。Google 会去掉 https://、www. 和尾部 /,剩下部分按面包屑(用 › 分隔)显示在 480px 宽的斜体行里。路径层级太深时末级会被截掉,看起来像另一个页面。

四是发版前自查 snippet。同一份 HTML 模板在本地改完就能确认标题与描述的实际显示效果,不用等收录、不用反复提交。

本页不做这些事:不抓取真实 SERP(那需要发请求,也拿不到个性化结果)、不做 A/B 预测排名、不校验页面的实际 SEO 配置。要检查页面上真实的标签是否存在,请用Meta标签分析;要按关键词反推标题写法,请用SEO标题生成器;要直接比字符数,请用标题标签长度检测。

原理和变量

核心是一个自建的字符宽度表 + 像素预算判定,全部本地计算,可逐行复核:

宽度表按 font-size: 20px 建:汉字与全角 20px(即 1.0 em)、ASCII 大写与数字 13.3px、小写 11px、空格 5.6px、窄字符 . , : ; ' " ! | i l 6px。判定规则是:widthOf(seg) <= 预算 就完整显示,否则按字符回退到不超预算的最长前缀再加省略号。

三段预算是怎么来的?标题按 600px、描述按 920px 每行、2 行共 1840px、网址行按 480px。这三个数字是桌面 Google 排版的经验值,会随版本、字号、实验分组变动——所以本页把预算写出来给你看,而不是把它当成不可见的常量。你按自己站点实际 SERP 截图量出来的宽度,直接改这三个常量就能对齐。

为什么必须先 trim 再取 scheme?因为 " javascript:alert(1)" 前面有一个空格,天真的 startsWith('javascript:') 判断会被绕过。本页的做法是 trim() 之后用正则 /^([a-z][a-z0-9+.-]*):/i 取出协议名,再对照只含 http 与 https 的白名单。

这里有一个必须讲清的事实:new URL() 不是安全网关。实测 new URL('javascript:alert(1)') 不抛错,它照样解析成功,返回 protocol='javascript:'、hostname=''、pathname='alert(1)'。只有 new URL('not a url') 这种连协议名都没有的串才抛 TypeError: Invalid URL。所以白名单必须自己写死,不能指望 URL 构造器替我们拦。而且即使放行了 http 与 https,本页依然不发请求——只把 URL 拆成 host 与 path 做排版推算。

还有一个细节:new URL() 会把协议名与主机名自动小写,所以 HTTPS://X.COM/A 解析出的 protocol 是 https:、hostname 是 x.com。比对协议时用 protocol 字段而不是原始字符串。

完整示例

默认这组(数值仅作演示):

对照下面表格里第 6 行:同样是 43 个字符,那条标题因为汉字占比更高,估宽 780px,被截得更多。这张表就是「字符数不能代表显示长度」的证据。

输入范围与对照表

三段输入的上限:标题 200 字符(超过 600px 的部分必被截断,再长没有信息量)、描述 500 字符(两行 1840px 最多装 92 个汉字或 167 个小写字母)、网址 2048 字符。超限会明确告知并拒绝,不静默截断。

网址协议白名单实测(15 条,全部只解析不访问):

输入的网址取到的协议判定原因
https://x.comhttps放行正常
http://x.comhttp放行正常
javascript:alert(1)javascript拒绝可执行脚本协议
JavaScript:alert(1)javascript拒绝大小写变形,被正则 i 标志捕获
javascript:alert(1)javascript拒绝前导空白,trim 后命中
data:text/html;base64,…data拒绝可执行 data 文档
data:image/png;base64,iVBORdata拒绝data 图片也不放行
file:///C:/Windows/…file拒绝本地文件系统
file://localhost/etc/passwdfile拒绝本地文件 + 主机
vbscript:msgboxvbscript拒绝老 IE 脚本协议
blob:https://x.com/uuidblob拒绝blob 本地对象
about:blankabout拒绝about 协议
ftp://x.com/a.txtftp拒绝ftp
chrome://settingschrome拒绝浏览器内部页
view-source:https://x.comview-source拒绝源码视图

下表是 12 条不同长度与汉字占比的标题逐条量宽的结果,可直接看出字符数与像素宽不是一回事:

#字符数估宽 (px)是否截断标题
124433.2否露点计算器_露点温度与相对湿度换算 - 柳泉工具
229481.7否WebP转PNG转换器_本地解码与体积对照表 - 柳泉工具
324433.2否日期转时间戳_时区与秒毫秒单位换算 - 柳泉工具
433480.1否CSS网格生成器_repeat与minmax参数输出 - 柳泉工具
519371.0否搜索结果预览工具_标题描述截断宽度还原
643779.7是露点计算器在线_气温湿度换算露点温度含简化公式误差对照与12行CSV导出 - 柳泉工具
7113.3否A
831487.5否WebP 转 PNG 转换器 - 本地浏览器内完成,不上传文件
943641.3是深度解析:Magnus 公式两个常数 17.625 与 243.12 的来历与误差实测
1030502.2否日期转时间戳:本地时区陷阱与 2038 年 32 位上限实测
1136469.3否CSS 网格生成器:auto-fill 与 auto-fit 的实测差异
1229527.5否搜索结果预览工具:600px 标题宽度与两行描述的截断口径
1325500.0否露点计算器:气温、相对湿度到露点的换算与简化式误差
1425448.5否WebP转PNG:本地解码、双层回退与体积放大倍数
1530482.3否日期转时间戳:Date.UTC 与本地时区构造的 8 小时差
1628419.7否CSS网格生成器:minmax 与 fr 的分配算法实测
1725500.0否露点计算器在线使用:输入气温与湿度立即得到露点温度
1834499.3否WebP转PNG转换器在线:体积、尺寸与 color type 对照

点「导出 CSV」拿走带 BOM 的表格。表格服务端直出,脚本不执行也能看到完整 12 行。

边界与精度

1. 像素模型是近似,不是渲染引擎。真实字距由浏览器的字体文件、字重与 hinting 决定,同一段文字在 Windows 的 Arial 与 macOS 的 Helvetica 上宽度能差几个百分点。本页的价值在于相对比较(哪条更可能被截、截多少),不是给出 Google 的精确裁切位置。所以表里一律保留 1 位小数,不假装精确到像素。

2. 字符数阈值与像素阈值是两套口径。业内常说「标题 50~60 字符」,那是像素预算的换算结果:600px ÷ 11px(小写字母宽)≈ 55 个小写字母;600px ÷ 20px(汉字宽)= 30 个汉字。所以「30 字符」和「580 像素」能同时存在,前者是汉字数、后者是像素宽。本页给的是后者。

3. 空串与纯空白分开处理。标题为空时预览区显示灰色占位「(标题为空)」而不是留白——因为真实 SERP 里没有 title 时 Google 会自己生成一个,那种情况应该去查页面而不是看预览。描述为空同理。网址为空则只显示前两段。

4. 网址的分隔符显示。Google 用 ›(U+203A)分隔层级,末级不重复显示在网址行。本页把 pathname 按 / 切开逐段用 › 连接;只有一段时只显示主机名。面包屑里的主机名会去掉 www.,与 Google 口径一致。

5. 描述按 2 行、1840px 判定。纯中文时 920 ÷ 20 = 46 个汉字每行、两行 92 个;纯小写英文时 920 ÷ 11 ≈ 84 个字符每行、两行约 167 个。这两个数字是「中文描述写多长才不浪费第二行」的依据。

6. 三个预算是经验值,会变。600px / 920px / 480px 会随 Google 的字号实验、桌面版布局调整而变。本页把它们做成页面内可见的常量并写进正文,你按自己站点的实际截图改这三个数即可对齐——这比相信一个藏在代码里的魔数要可靠。

7. 零请求是本页的可验证承诺。本页对用户填的网址只调用 new URL() 做字符串解析,不发任何网络请求。你可以在开发者工具的 Network 面板里自查:生成预览、载入示例、导出 CSV,全部操作之后面板应始终为空。如果某个版本出现了请求,那就是出了故障,请把请求 URL 反馈给我们。

常见问题

我填的网址会被你们访问吗?会不会泄露我的站点?

不会。本工具对网址只做字符串解析(new URL() 拆出协议、主机名、路径),不发任何网络请求,你可以在开发者工具的 Network 面板自查——打开页面、粘贴内容、生成预览、导出 CSV,做完之后面板应该始终是空的。这条承诺对 javascript:、data:、file: 这类协议尤其重要:它们被白名单直接拒绝,既不会被请求,也不会被塞进任何可执行上下文。

我的标题只有 28 个字符,为什么还是被截断了?

因为截断按像素不按字符。28 个字符如果全是汉字,宽度是 28 × 20 = 560px,没问题;但如果混进英文与数字,汉字占比一降,字符数不变而像素宽可能反而更小——反过来,汉字占比高时同样 28 个字符就更容易撞上 600px。你可以在预览区看那枚「已截断」徽标,以及统计条里「标题估宽 / 上限」的具体数值,把标题改短或减少汉字占比都能解决。

描述写满 500 字符是不是更好?

不是。描述的预算是两行 1840px:纯中文最多 92 个汉字、纯小写英文约 167 个字符。写到 500 字符时,超出部分永远不会被看到,纯粹是浪费字数。多数情况下 70~80 个中文字符(约 120~140 px × 2 行内)已经把两行用得比较充分。塞满反而有风险:如果前 40 个字没把核心信息说清,后面的内容在 SERP 里等于不存在。

为什么网址显示的是「liuquan.net › jisuanqi › ludiandianjisuanqi」而不是完整的 https 地址?

因为 Google 会去掉协议名、www. 前缀和尾部 /,剩下的路径层级用 ›(U+203A)分隔显示在 480px 宽的行里。本页照这个口径还原,末级不重复。所以预览里看到的面包屑本身就是 SERP 的实际形态——如果你想让末级更醒目,办法是缩短路径层级(少两层目录),而不是改 title。

宽度估算的 20px、13.3px、11px 这些数是怎么来的?

它们是按 font-size: 20px 建的近似字符宽度表:汉字是全角、宽等于 1.0 em 即 20px;大写字母与数字是 0.665 em ≈ 13.3px;小写字母 0.55 em = 11px;空格约 0.28 em 即 5.6px;窄字符(. , : ; ' " ! | i l)约 0.3 em 即 6px。这套表的价值是可解释、可自己改:你可以把 W 里的数字换成自己站点正文字体的实测宽度,预估就更准。本页也把这份表写在正文里,方便你核对。

我改成 javascript:alert(1) 会不会在页面上弹出来?

不会,而且这条输入会被明确拒绝。原因是三层防护:一,先 trim() 去掉前后空白,再用正则取协议名,所以 " javascript:..." 这种带前导空格的变形也会被抓住;二,协议名对照只含 http 与 https 的白名单,javascript、data、file、vbscript、blob、about、view-source 全部拒绝;三,被拒的字符串不会被写进 DOM,错误区用的是 textContent 而不是 innerHTML。

为什么 new URL() 拦不住 javascript:?

因为它本来就不是过滤器,只是解析器。实测 new URL('javascript:alert(1)') 不抛错,返回 protocol='javascript:'、hostname=''、pathname='alert(1)'——它认为这是一个合法的、非特殊的 URL。只有 new URL('not a url') 这种连协议名都没有的串才会抛 TypeError: Invalid URL。所以安全判断必须自己写白名单,这一条对任何「用户输入 URL」的场景都成立。

这个预览和真的 Google 结果会一模一样吗?

不会完全一样,差距在三处:一,Google 的 600px / 920px / 480px 预算会随版本与实验分组变动,本页用的是固定经验值;二,Google 会按查询词高亮命中词(<strong> 或颜色),本页不做高亮;三,移动端与桌面的预算不同(移动端约按视口宽的 88 % 折算,标题行更窄),本页只给桌面口径。要完全对齐只能对着自己站点的真实搜索截图逐段量。要检查页面上的真实标签而不只是猜显示效果,用SEO清单工具逐项过一遍。

相关工具