文档中心/🩺 排版规范 ✏️ 编辑此页

微信排版规范 · 落地说明

依据:微信公众平台官方文档《能力接入 / 微信公众平台编辑器插件开发规范》 (https://developers.weixin.qq.com/doc/service/guide/product/plugin_spec.html)

博客号在三个层面落地了这份规范:

  1. 编辑器「排版体检」:发布前一键静态检查,逐条指出违规点并引用规范编号(编辑器右上角「体检」按钮)
  2. 存储净化器(src/sanitize.ts):保留规范友好的属性(data-w、data-ignore-width、data-no-dark…),剥除危险内容
  3. 默认主题(src/themes/wechat.css):正文 17px / 1.75 行高,响应式无固定宽;默认保持明亮配色(站长偏好关闭了自动 Dark Mode,恢复方式见该文件内注释)

以下是规范要点摘要与博客号的对应实现,供主题/插件开发者参考。


1. CSS 属性使用规范

1.1 opacity —— 禁止隐藏真图叠 SVG

  • 规范:不要把 img 的 opacity 设为 0,再用带背景图的 SVG 叠在原位。真图被隐藏后,发布后无法在编辑器里修改图片。
  • 博客号:体检规则 1.1 opacity;粘贴内容中的此类结构会被警告。

1.2 caret-color —— 光标必须可见

  • 规范:禁止把输入光标颜色设为全透明,作者会找不到输入位置。
  • 博客号:编辑区强制 caret-color: var(--green);体检规则 1.2 caret-color 检查粘贴内容。

1.3 line-height —— 不得小于字号

  • 规范:容器行高小于字号时,多行文字会重叠。排除场景:纯图片无缝拼接(元素内无文字)、实际只渲染一行的文字。
  • 博客号:体检规则 1.3 行高过小(px 与 unitless 两种写法都检查);默认主题正文 17px / 1.75。

1.4 width —— 禁止固定宽度破坏响应式

  • 规范:固定宽度会造成「居中不一致 / 水平溢出 / 不同屏幕占比差异」。建议给 <img> 加 data-w(图片原始像素宽度)作为加载超时后的宽度兜底。
  • 豁免:横向滚动容器、视觉裁剪特效、第三方固定尺寸组件等有意为之的场景,在节点上加 data-ignore-width(对自身及子树生效)。
  • 博客号:编辑器插入图片时自动探测并写入 data-w;体检规则 1.4 固定宽度(识别 data-ignore-width 豁免并提示确认)与 1.4.3 data-w;净化器原样保留这两个属性。

1.5 height —— 别让内容不可见

  • 规范:height:0 且含文字 → 移动端整段不可见;固定小高度 + 内容溢出 → 被裁剪。排除:SVG 交互容器、无文字内容、可滚动容器。
  • 博客号:体检规则 1.5 高度为 0。

1.6 text-align —— 禁用 start / end

  • 规范:不同终端对 start/end 兼容不一,会造成部分设备居中、部分居左。
  • 博客号:体检规则 1.6 text-align;「一键修复」会把 start/end 改为 left。

1.7 SVG animate begin —— 兼容 PC

  • 规范:SVG 动画若只在 touchstart 触发,PC 端无法点击,应写 begin="touchstart; click"。
  • 博客号:出于安全考虑净化器会整体移除 <svg>(内联 SVG 是常见 XSS 载体),如需 SVG 动图请使用 GIF/视频或截图。

1.8 pre —— 不要包裹普通正文

  • 规范:<pre> 自带 white-space:pre 不自动换行,窄屏会被截断。普通段落用 p / section。
  • 博客号:编辑器「代码块」按钮只往 pre 里放 <code>;体检规则 1.8 pre 标签 检查无 code 的纯文本 pre。

2. 文章结构规范

  • 2.1 嵌套层级:同标签名 + 同内联样式 + 单子节点的连续嵌套 ≤ 10 层(图片/视频/SVG 等媒体标签除外),超出会被编辑器自动精简。→ 体检规则 2.1 嵌套层级。
  • 2.2 span[leaf]:只能包含行内元素或文本。→ 从公众号粘贴的内容经净化后仅保留白名单标签。
  • 2.3 section[nodeleaf]:只能包裹官方特定组件或 img。

3. 字体使用规范

  • 规范:不建议设置任何 font-family,公众号默认字体栈为 "mp-quote", PingFang SC, system-ui, -apple-system, BlinkMacSystemFont, …
  • 博客号:默认主题沿用该字体栈;体检规则 3 字体使用 提示自设字体族(净化器不强行剥除,保留作者自由度)。

4. Dark Mode 规范

  • 4.1 颜色:文字与背景对比度适中;文字下方的渐变背景在 Dark Mode 下会被算法转成纯色,尽量避免;纯装饰渐变(上方无文字)不受影响。
  • 4.2 结构:同一段多文本共用一个背景时,把背景写在公共容器上,别逐个文本节点设置;保持「结构顺序 = 视觉顺序」,别用绝对定位打乱。
  • 4.3 图片:别用图片承载纯文本(算法无法转换其中的文字);透明底图片注意在 Dark Mode 正文底色 #191919 上的对比度。
  • 4.4 SVG:如需 SVG 线条颜色跟随深浅色,使用 stroke="currentColor" fill="currentColor"。
  • 4.5 技巧:data-no-dark 让单个节点跳过转换;不要使用 !important;确认无碍的告警可用 data-ignore-dm="low-contrast text-bg-gradient" 豁免检测。
  • 博客号:!important 在净化时被剥除、体检提示;data-no-dark / data-ignore-dm 属性原样保留;wechat 主题默认保持明亮配色(站点不做 prefers-color-scheme 自动 Dark Mode)。

5. 博客号体检规则一览(编辑器 → 体检)

规则号 名称 级别 可一键修复
1.1 opacity 隐藏图片 ⚠️
1.2 caret-color 透明 ⚠️
1.3 行高小于字号 ⚠️
1.4 固定宽度(含 data-ignore-width 提示) ⚠️
1.4.3 图片缺 data-w 💡
1.5 height:0 隐藏文字 ⚠️
1.6 text-align: start/end ⚠️ ✅
1.8 pre 包裹普通正文 ⚠️
2.1 同标签嵌套 ≥ 10 层 ⚠️
3 自设 font-family 💡
4.1.2 渐变背景上有文字 💡
4.5.2 使用 !important ⚠️ ✅
无障碍 img 缺 alt 💡

官方还提供基于 Puppeteer 的完整校验 CLI(含需真实布局测量的 width/height/叠字检测): https://github.com/wechatjs/verify-article-structure-spec —— 需要更严格校验时可本地运行。