肉眼逐屏看不全的背景硬缝与低对比文字,
让真浏览器逐像素扫出来
驱动你本机已装的 Edge 或 Chrome,按真实视口逐屏截图,用像素判定「文档态硬接缝」与逐行合成后的文字对比度, 再靠两轮反证排掉误报,最后交一份能直接转发的 HTML / PDF 证据报告—— 每个问题都带屏幕坐标、台阶量级和是哪个元素画的。
它替掉的是三件很费人、又最容易漏的事
做深色 + 渐变背景的站时被这几个问题反复咬过,市面上的截图对比工具又接不住——所以我们自己写了一个。
背景接缝「只在滚动时出现」
固定视差层、分段背景、辉光裁断,单屏截图完全正常,滚到某一屏才留下一条明度台阶。人工翻屏要么看不见,要么看见了不知道是哪层画的。
- 逐屏连续采样整页,跨屏也能定位到文档 Y 坐标
- 量级用「亮度台阶」表示,能比较严重程度
自动化工具误报成灾
截图对比类工具把正常渐变、卡片投影、1px 分割线全报成缺陷,客户第一版就被误报劝退。误报比漏报更贵。
- 关掉装饰层复扫:台阶消失 ⇒ 判为背景自身,不算缺陷
- 同一屏幕行在多数屏命中 ⇒ 固定背景,剔除
- 留白列被内容压住 ⇒ 降级为提示,不判失败
对比度「算错了还以为算对了」
文字压在多层半透明 + 渐变底上,静态样式表算不出真实前景色;Lighthouse 只看 DOM 属性,看不出合成结果。
- 取截图上文字所在像素的实际背景,逐层合成透明度后再算
- 正文 ≥4.5、大字(≥24px)≥3.0,逐段给结论
一轮审计跑完,机器替你做了这些
整条链路只依赖本机浏览器的 CDP 协议:PNG 解码、WebSocket 客户端都是手写的,不装任何包。
启动这一层为什么单独说
headless 浏览器最容易在客户机器上翻车的就是「偶发秒退」和「失败后留一堆孤儿进程」。我们把这三条钉死:
- 端口必须
127.0.0.1与::1两个协议栈都探测为空闲才使用(IPv4 被占时浏览器会静默改绑 IPv6,进而连到别人的实例) - 临时 profile 目录由系统保证唯一,启动前清残留单例锁
- 秒退自动换端口 + 换 profile 重试;每一条失败路径与 Ctrl+C / 崩溃都会杀进程树、删目录,不留孤儿
跑一次的代价
全部在你本机完成,不上传页面、不留存数据,也不需要什么服务:
- 单页三端审计:约 1–3 分钟(视页面长度与动效)
- 报告自含截图,可整份转发,不需要再打开原站
- 纯命令行,能挂进流水线做发版门禁
判据口径全公开
所有阈值都从代码里抽出来按档位配置,每个数字都标明是「量出来的」还是「拍的」;拍的会在配置里写 TODO,
等首批真实样本回来复核。我们宁可让你看到判据本身,也不给一个黑箱分数。
| 判据 | 口径 | 怎么来的 |
|---|---|---|
| 文档态硬接缝(失败级) | 亮度台阶 ≥ 8 级,且一行内跨过去(锐度 ≥0.8) | 真缺陷实测 12 / 29 / 37 级,逐行噪声 2–6 级 — 阈值取在两者之间 |
| 同一条但仅提示 | 3–8 级(深色档)/ 2–8(浅色)/ 1.5–6(纯色) | 星云留白里肉眼分辨不出的量级不外判,避免误报 |
| 误报闸 ①:背景自身 | 同一屏幕行在 ≥50% 的屏命中 ⇒ 剔除 | 固定视差 / 网格层是「看着像缺陷」的主要来源 |
| 误报闸 ②:留白被压 | 左右留白列被非内容块覆盖率过高 ⇒ 降级为提示 | 组件撑满整宽的窄屏,「只看留白列」前提不成立 |
| 内容边缘不算污染 | 满屏宽(≥95% 视口)的块不计入留白污染 | 它的边压在视口边界上,计入等于自废判据、把真缺陷降成提示 |
| 文字可读性 | 正文 ≥ 4.5,≥24px 大字 ≥ 3.0 | 对齐 WCAG AA;背景取截图上该像素的合成结果 |
| 成因归因 | 当前 DOM 元素边界贴合硬缝(≤12px)+ 宽度占比判据 | 不需要历史基线,第一次跑就能给出「谁的 CSS」 |
说明:工具不做「打分」。输出的只有具体位置(文档 Y 坐标 / 屏幕行)、量级、肇事元素和它为什么像缺陷的成因, 修与不修由人判断——把不确定交给算法,是把误报换成另一种形式。
三档内置阈值 + 自动选档
同一组数字搬到浅色纯色站就会大面积误报——所以判据分档。也可以用 --profile my.json 只覆盖你要改的字段。
适用
深色底 + 固定视差背景 + 半透明卡片的站。这是我们标定这一档的站点类型:带视差光斑、辉光分割线、多层 position:fixed 背景层。
这一档修掉的真实案例
自家官网的面包屑区被扫出 +37 级硬带:分割线辉光在裁断处留下一条明度台阶,肉眼在深色底上几乎看不出来,滚动时却会一闪而过。
示意图:三段背景的亮度差异被判定为两条硬边界,归因指向分割线容器自身。
适用
白 / 浅灰底、实色卡片、少量渐变的内容站。背景本身干净,判据可以比深色档更严。
这一档的验证方式
自带两个真机夹具:一页「干净对照页」(满屏渐变 + 卡片投影 + 1px 亮线),一页「埋点缺陷页」(人为画出硬带、渐变字配黑阴影、浅灰正文)。
- 干净页:0 失败、0 提示、文字全部达标(不许误报)
- 埋点页:埋的几个缺陷全部被抓到,且能归因到埋进去的那个元素
适用
整站单一底色、无渐变无纹理。理论上留白列应当完全平:任何台阶都是元素画的。
诚实说明
这一档的失败线是拍板值,不是实测标定值——配置文件里就直接写了 TODO。等首批客户样本回来复核再收紧或放宽。我们不会把它说成「行业阈值」。
自定义档位支持 "extends": "light" 深合并,只写你要改的字段即可,其余继承。
先拿自己开刀:可复核的自检数据
下面每一行都是这台机器上跑出来的结果,不是宣传数字。工具对外之前,验收标准是「先扫自己扫得出问题」。
知微工作室官网经本工具复测
桌面 1440 / 平板 834 / 手机 390 三端逐屏采样,含 116 段正文对比度探针。
- 文字可读性:0 不合格
- 文档态失败级硬缝:0 条
- 仅提示项:1 条(定价页 +4.88 级,低于 8 级失败线,肉眼不可分辨)
- 此前同一工具链在官网共挖出并修掉 9 个真实渲染缺陷,含上文那条面包屑 +37 级硬带
这一档数据的意义在于「修完之后确实扫不出来」,而不是「扫得出一堆问题」。修完复扫为 0,是这条链路有效性的证据。
真机套件连续三轮
离线逻辑 + 真机夹具 + 启动稳健性三项合并计数。
| 范围 | 结果 | 说明 |
|---|---|---|
| 离线 + 真机夹具 | 66 ✓ / 0 ✗ | 连续三轮一致 |
| 其中启动稳健性 | 12 ✓ / 0 ✗ | 端口占用 / 秒退重试 / 并发 / 无孤儿 |
| 线上三端回归 | 62 ✓ / 0 ✗ | 与内部标定值对齐,确认没 regression |
| 跑完残留 headless 进程 | 0 | 按命令行特征过滤,含崩溃路径 |
「跑完不留孤儿」这一条以前是写在注释里的承诺,没兑现:实测残留 35 个临时 profile 目录。现在由回收表与退出钩子强制,且新增的秒退重试路径实测 0 新增残留。
已证伪的三类假阳性
- 「背景接缝」实为未显式设窗口尺寸,headless 默认 800×600 的合成器台阶
- 「低对比」实为把入场动画未定格的半透明帧当成了最终态
- 「硬缝」实为卡片 1px 亮边——内容边缘,不是背景问题
三类都进了判据层做长期防线,不是靠人工挑刺绕过。
不做的判断
- 不做主观美感评分,只报可量测的像素事实
- 不替你决定「这条要不要修」,只给位置、量级、成因
- 不接需要登录态的页面:只审计免登录可访问的 URL
已知边界
- 只支持带 CDP 的浏览器(Edge / Chrome),Firefox、Safari 不支持
- PDF 走浏览器打印,长报告分页位置不如人工排版;对外交付以 HTML 为准
- 重动效页面需调等待时长与采样屏数参数
报告长什么样
一份自包含 HTML:结论区给「有没有要修的」,证据区把截图直接标注上问题位置,归因区写清是谁的 CSS。可整份转发给客户,也可以另存 PDF。
y=1873 台阶 +29.4
跨屏边界处亮度台阶超过失败线,反证轮关闭装饰层后仍存在 ⇒ 非背景自身。
归因:section.cta-band::before(辉光渐变在容器裁断处留下台阶)
3.12 y=946
正文段落合成后前景/背景比值低于 4.5;背景为两层半透明叠渐变。
归因:.hero p 颜色 #5d7fa6 落在 .veil 之上
y=3203 台阶 +4.88
低于失败线(8 级),深色留白中肉眼不可分辨。默认不外判,供排查参考。
组件轮廓被判为背景级别已撤销;留白列被内容压住,按口径降级为提示。
报告里必定包含的四件事
- 位置:文档 Y 坐标 + 所属视口,不用你再去翻是哪一屏
- 量级:亮度台阶级数 / 对比度比值,可比较、可复查
- 成因:贴合边界的内容元素选择器,及其被判为背景/内容/固定的推理依据
- 证据:截图上画出标注框,不靠文字描述让你脑补
脱敏是产线的一部分
报告渲染前会扫一遍内部标识与本地路径,命中即拒绝输出——所以这份文件可以整份发给客户、也能进公开工单。
想要针对你自己站点的一份真实样例报告?发邮箱地址即可,内测期先免费出一份看看合不合用。
命令与流水线接入
没有配置文件要填、没有服务要起:一条命令出一个 URL 的三端结论。
# 三端审计 + HTML 报告
node index.js audit https://example.com
# 自动按站点特征选档,顺带导出 PDF
node index.js audit https://example.com \
--profile auto --pdf
# 只看背景接缝 / 只看文字可读性(终端文本)
node index.js seams https://example.com
node index.js probe https://example.com
# 批量:一个 URL 一行,逐页出报告 + 终端汇总
node index.js batch urls.txt --out ./reports
# 列出内置档位及其阈值
node index.js profiles
# CI 门禁:有失败项就退非 0
node index.js audit https://staging.example.com \
--json --views desktop || exit 1
环境要求
- Windows / macOS / Linux,Node 18 以上
- 本机已装 Edge 或 Chrome(Firefox 无 CDP,明确不支持)
- 零 npm 依赖:PNG 解码与 WebSocket 客户端都是自带实现
- 浏览器路径可用环境变量指定,无需改代码
不联网上传任何页面内容:审计在被测页面与你本机浏览器之间完成。
内测期怎么开始
现在不做正式定价公示。首批客户跑通、拿到真实误报/漏报样本之后,档位与价格才敢定死。
单页三端(桌面 / 平板 / 手机)审计 + 一份可转发的证据报告,当天出。
- 含判据口径说明,告诉你为什么某条只算提示
- 报告不满意全额退,不用解释理由
- 内测期反馈缺陷样本可换多页额度
多页 / 整站 / 接入 CI 的报价邮件里按页面数说,不写死高价,也不搞阶梯话术。
邮箱询价 · cqsj6667@agent.qq.com也可以只买「怎么判」这一层
如果你已经有自己的巡检脚本,想要的是判据与阈值口径(含两道反证闸的实现思路),我们可以只给一份《判据口径与阈值标定说明》,不含跑站。
这一项按咨询计,邮件说清你的技术栈即可给结论。
不适合本工具的活
- 需要登录态、支付流程内页的审计
- 主观视觉风格评估、竞品美学对比
- 要求给出「设计分数」的报告书
- Safari / Firefox 专属渲染问题
这几种我们不接——不是客气,是确实给不出可信结论。
几个一定会被问到的问题
和 Lighthouse / 截图对比工具比,差别在哪?
Lighthouse 的对比度检查读 DOM 样式属性,看不出文字底下压了几层半透明和渐变之后的真实像素;本工具直接从截图取背景像素再算比值。截图对比类工具需要一个「正确基线」,一旦没有基线就只能报「这里不一样」;本工具不依赖基线,靠当前 DOM 的元素边界贴合来指认肇事元素。
更关键的是误报处理:关掉装饰层复扫 + 屏幕行分布两道闸,把「看起来像缺陷的背景」和「页面画的硬缝」分开。
为什么必须用真浏览器?Playwright 之类不是更省事?
结论要能拿去和客户争,就必须是被测页面在真实渲染管线里跑出来的样子:合成器分层、亚像素取整、滤镜裁断这些在 DOM 里推不出来。我们选 CDP 直连本机已装浏览器,是为了不再引一层依赖,也避免「装了包但客户机器装不上」——这是对外产品最容易死的地方。
报「0 条失败」我怎么信?
三条路都可以自查:一是报告里每条提示项都给坐标与量级,可以自己滚到那一屏看;二是判据口径在本页全部公开(含失败线与两道闸的比值),不存在黑箱;三是自带两个真机夹具——干净页必须 0 误报、埋点页必须全抓到,你拿到工具第一件事就可以跑这两个夹具验证有效性。
会不会把我站上未公开的内容传走?
不会。工具在你本机驱动你本机的浏览器,截图与报告都写在本地目录,全程没有第三方服务、没有上报。要发版前,报告和源码还各做一次脱敏自检,命中内部标识就直接拒绝输出。
能接进 CI 吗?跑一次多久?
能。有失败项返回非 0 退出码,加 --json 出机器可读结果;只用文本输出做卡口也可以。单页三端约 1–3 分钟,取决于页面长度与动效多少;批量模式一页一份报告,最后给终端汇总。
阈值是不是拍脑袋?
深色档与浅色档的失败线来自实测标定(真缺陷 12/29/37 级、噪声 2–6 级),提示线按「肉眼分辨不出就不外判」定;纯色档的失败线 6 级是拍板值,配置文件里直接写了 TODO 等真实样本复核。每个数字的来历在配置注释里。
把你站点上那条「滚动时才出现的缝」交出来看看
发站点地址到邮箱,内测期先出一份真实报告给你看判得准不准;不合适的判据我们可以调档。
cqsj6667@agent.qq.com24 小时内响应 · 数据不留存 · 报告可整份转发 · 知微工作室主站