#教程 dw, dm, dy, d18m 是何意?万物可 Badge | 定制漂亮精致小徽章,打造眼前一亮 README

92 阅读6分钟

最近看到一个开源库 sse-stuntman 的徽章独具一格:

sse-stuntman 漂亮精致的徽章

就在想我的项目也能用上就好了。

平常我们的徽章都是固定的配色、固定 logo 甚至固定的文字。

而这个库的徽章新颖之处在于,logo 是自定义的(coverage 的 logo 是 CS),logo 颜色,dependencies 背景色黄色都是自定义。这是如何做到的呢?

平常我们用的最多的是 npm 下载量徽章,其实 downloads 徽章支持四种统计维度:

[dw, dm, dy, d18m] 最近 1 周 / 1 月 / 1 年 / 18 个月下载量

除了展示 npm 下载量还支持多达 73 项服务的下载量!

Snipaste_2026-07-28_13-51-01.jpg

学完后我们甚至可以打造一个天气 badge。

徽章原理

我们从两个维度来说。

从能力来说:徽章(Badge)是 img.shields.io 公司提供的图片服务,分成静态徽章和动态徽章(后者依赖该公司服务端提供数据能力,比如 npm 的下载量)。

从格式来说:徽章其实是一段 markdown 代码,图片格式而已 ![alt](src)。

当然 HTML 片段也是合法的 markdown,可以被 github 或掘金等平台支持,故也可以是 <img alt="[alt]" src="<src>" />(只有 src 必选,但建议加 alt 这样即使图片 broken 也能展示图片含义)。

徽章拆解

静态徽章

徽章分成两部分,path 和 query。

https://img.shields.io/badge/label-message-greenyellow 这种格式称为静态徽章,即里面的文字和颜色都是固定的,可以看出 path 包含三元素“label message color”,这是我们可以定制的部分。

当没有动态服务可以满足时候就可以使用,比如 sse-stuntman 的依赖数量徽章,这个库以 0 依赖轻量级为特色,所以他加了一个 dependencies 0 的徽章。代码很简单:

https://img.shields.io/badge/dependencies-0-green

但是目前渲染的是还和 sse-stuntman 不一样,少了 logo 以及左半部分背景色不是黄色。

我们还需要学习更多“Query 查询参数”。下面文字来自官方文档。

静态徽章仅接收一个必填路径参数,该参数编码内容分为以下两种格式:

  1. 标签、提示文本、颜色(Label, message and color),三者以短横线 - 分隔。示例: 任意文字:你自定义内容转存失败,建议直接上传图片文件 — 对应地址:img.shields.io/badge/any_t…

  2. 仅提示文本与颜色(Message and color only),二者以短横线 - 分隔。示例: 仅展示提示文本转存失败,建议直接上传图片文件 — 对应地址:img.shields.io/badge/just%…

URL 传入字符徽章展示字符
单下划线 _ 或 %20空格
双下划线 __单下划线 _
双短横线 --单短横线 -

这里的意思是如果你想在 label 里面增加空格,你得写 %20,以此类推。

更多静态徽章示例

支持十六进制、RGB、RGBA、HSL、HSLA 色值以及 CSS 标准颜色名。 注意: 部分内置颜色名的色值与原生 CSS 标准色存在差异。完整颜色名列表可查阅 badge-maker 文档。

动态徽章

我们常见的动态徽章有 npm version 和 npm downloads。每一种动态徽章都有可交互 playground:

npm version 交互 playground

Dynamic badges 展示具体项目指标,目前 shields.io 为数百个服务提供了徽章。

动态徽章又分为内置服务和自定义。

内置服务是 shields.io 给开发者提供了现成能力,这是徽章具备的动态变化魔力的基础。

自定义又有 6 种格式。

6 种自定义动态徽章

动态 JSON 徽章

动态 JSON 徽章支持通过 JSONPath 选择器从任意 JSON 文档中提取任意字段值,并将该值展示在徽章上。

比如我们有一个 package.json url raw.githubusercontent.com/legend80s/p… 可以如此展示其 name query=%24.name 24% 是 $ 的转义:

img.shields.io/badge/dynam…

举个更加有趣的例子,实时北京天气预报

我们可以展示北京当前温度(注意是天气数据不是写死的是实时的,每天打开都不一样)

img.shields.io/badge/dynam…

北京当前温度 2026-7-28 36℃

体感温度:

北京当前温度 2026-7-28 39℃

把 temp_C 改成 FeelsLikeC 即可。

为什么知道这么写?

几个技术要点:

  1. url — 必填。指向一份 JSON 文档
  2. query — 必填。用于查询该 JSON 文档的 JSONPath 表达式。示例:$.name

对于北京天气 url 是 https://wttr.in/beijing?lang=zh-cn&format=j1,query 是 query=$.current_condition[0].temp_C,label 是 北京当前温度,摄氏度是通过 suffix=℃增加的。更多参数见 Dynamic JSON Badge。

Endpoint Badge

img.shields.io/endpoint?ur…

只要你的 your_api 返回如下格式就会展示对应内容。

{ "schemaVersion": 1, "label": "hello", "message": "sweet world", "color": "orange" }

有什么用呢?当无论静态还是内置服务都无法展示徽章内数据,因为这些数据可能存在你的服务器,就可以开放一个符合返回格式的 API endpoint。就是这么简单。

回顾下 Path 和 Query:

Path

/badge/ 都是静态 badge,动态 badge 服务不同 path 不同。举例:

Query

我们把 dependencies 0 徽章源码拿出来

https://img.shields.io/badge/dependencies-0-green?logo=npm&logoColor=212121&labelColor=ffc44e

问号后面的就是 query

?logo=npm&logoColor=212121&labelColor=ffc44e

现在可以看到 logo logoColor labelColor 如何定制。那么还有哪些参数呢?

参数说明
stylestring 类型
可选值:flat、flat-square、plastic、for-the-badge、social
如未指定,此徽章默认样式为 flat
示例:flat
logostring 类型
来自 Simple Icons 的图标标识(slug)。点击 simple-icons 上的图标标题即可复制其 slug,也可在 simple-icons 仓库的 slugs.md 文件中查找。
示例:appveyor
logoColorstring 类型
图标的颜色(支持十六进制、RGB、RGBA、HSL、HSLA 及 CSS 命名颜色)。仅适用于 Simple Icons 图标,不适用于自定义图标。
示例:violet
logoSizestring 类型
设置 auto 可使图标自适应缩放。适用于部分较宽的图标(如 amd、amg)。仅适用于 Simple Icons 图标,不适用于自定义图标。
示例:auto
labelstring 类型
覆盖左侧默认文本(空格或特殊字符需要 URL 编码!)
示例:healthiness
labelColorstring 类型
左侧部分的背景颜色(支持十六进制、RGB、RGBA、HSL、HSLA 及 CSS 命名颜色)。
示例:abcdef
colorstring 类型
右侧部分的背景颜色(支持十六进制、RGB、RGBA、HSL、HSLA 及 CSS 命名颜色)。
示例:fedcba
cacheSecondsstring 类型
HTTP 缓存时长(规则会自动为每个徽章推断默认值,低于默认值的设置将被忽略)。
示例:3600
linkstring[] 类型
指定点击徽章左侧/右侧时的跳转行为。注意:此功能仅在将徽章嵌入 <object> HTML 标签时有效,不适用于 <img> 标签或标记语言。

上面是通用参数,不同服务还有自己的参数,比如 npm version 可以指定 registry(公司内部包就可以派上用场了)。

| **`registry_uri`** | 示例:`https://registry.npmjs.com` |

定制与众不同的徽章

接下来我们把 sse-stuntman 这个库的徽章源码抠出来学习,然后复制到自己的 README,并定制成具有自己项目印记的小徽章(badge)。

<!-- https://github.com/legend80s/sse-stuntman/blob/main/README.md -->

<p>
  <a href="https://www.npmjs.com/package/sse-stuntman" target="_blank">
    <img src="https://img.shields.io/npm/v/sse-stuntman.svg?logo=npm&logoColor=cyan" alt="npm version" />
  </a>

  <a href="https://www.npmjs.com/package/sse-stuntman?activeTab=dependencies" target="_blank">
    <img alt="0 dependencies" src="https://img.shields.io/badge/0-green?logo=npm&logoColor=212121&labelColor=ffc44e&label=dependencies&color=green&color=212121" />
  </a>

  <a href="https://www.npmjs.com/package/sse-stuntman">
    <img src="https://img.shields.io/npm/dm/sse-stuntman.svg?logo=npm&logoColor=cyan" alt="npm downloads" />
  </a>

  ![coverage](https://img.shields.io/badge/95.8%25-green?logo=counterstrike&logoColor=cyan&label=coverage&color=green&color=212121)
</p>

掘金也支持,比如下面的徽章就是上述代码渲染的,注释不是我截图,是实实在在通过 HTML 代码渲染的,是动态的,当 sse-stuntman 的下载量变化了,你再来这篇文章看,会发现数字是事实同步的。

这就是 badge 的魔力。它不仅仅是一个静态的图片。

前端开发者特别容易理解

image.png

但是上述有个问题,就是 badge 之间会有下划线,这是因为 <a /> 链接导致的,改成 markdown link 语法即可:

    <p>

      [![NPM Version](https://img.shields.io/npm/v/sse-stuntman.svg?logo=npm&logoColor=cyan)](https://www.npmjs.com/package/sse-stuntman)
      
      [![0 dependencies](https://img.shields.io/badge/0-green?logo=npm&logoColor=212121&labelColor=ffc44e&label=dependencies&color=green&color=212121)](https://www.npmjs.com/package/sse-stuntman?activeTab=dependencies)
      
      [![NPM Downloads](https://img.shields.io/npm/dm/sse-stuntman.svg?logo=npm&logoColor=cyan)](https://www.npmjs.com/package/sse-stuntman)

      ![coverage](https://img.shields.io/badge/95.8%25-green?logo=counterstrike&logoColor=cyan&label=coverage&color=green&color=212121)
    </p>

注意此种写法第一个 bage 和 <p> 必须留有至少一个空行,否则 badge 将展示成源码而非图片。

还可以优化下,让 badge 居中 <div align="center">。其实这个技巧也可以用在掘金里面。

    <div align="center">

      [![NPM Version](https://img.shields.io/npm/v/sse-stuntman.svg?logo=npm&logoColor=cyan)](https://www.npmjs.com/package/sse-stuntman)
      
      [![0 dependencies](https://img.shields.io/badge/0-green?logo=npm&logoColor=212121&labelColor=ffc44e&label=dependencies&color=green&color=212121)](https://www.npmjs.com/package/sse-stuntman?activeTab=dependencies)
      
      [![NPM Downloads](https://img.shields.io/npm/dm/sse-stuntman.svg?logo=npm&logoColor=cyan)](https://www.npmjs.com/package/sse-stuntman)

      ![coverage](https://img.shields.io/badge/95.8%25-green?logo=counterstrike&logoColor=cyan&label=coverage&color=green&color=212121)
    </p>

本系列每 1 个观点都追溯到 1 行源码、1 段官方文档。