css-color-converter vs color

Benchmark report for the library migration introduced in abfc4f987e. The measurements focus on the code paths that matter to Shields: CSS color parsing, normalizeColor()-style normalization, and brightness()-style RGB conversion.

Generated2026-04-11T14:26:21.785Z
Git Branchuse-modern-color-lib
HEADabfc4f987e
Nodev25.9.0
Runtimedarwin arm64
CPUApple M1 Pro
Memory16.0 GB

Executive Summary

Best valid-path result css-color-converter was fastest in normalizeColor-style mixed badge inputs.
Single SVG badge view Across the tested SVG badge scenarios, the end-to-end gap stayed within roughly 0.21-0.41 microseconds per badge, so rendering work dominates.
Single JSON badge view For JSON badge payloads, css-color-converter saved about 0.54 microseconds per badge, making color normalization a larger share of the work.
Invalid input behavior On invalid inputs, color pays for exception creation/catching while css-color-converter returns null.
Capability difference color supports additional inputs used in the migration, including clamped negative RGB values and hwb(...).

Per-Badge Timings

The earlier sections benchmark color handling in isolation. This section measures the full badge path instead: a local makeBadge() equivalent wired to the old and new color implementations, using the same renderers and verifying that both versions produced identical output for each scenario.

Median values below come from 7 measured rounds after warmup. This is the most direct answer to how much time one badge spends here.

Scenario Example badge css-color-converter color Winner Gap per badge Gap per 10k badges
Simple SVG with named colors build / passing / brightgreen / grey / flat 22.25 microseconds 22.04 microseconds color 0.21 microseconds 2.10 ms
SVG with CSS colors coverage / 95% / papayawhip / #ABC123 / flat 22.61 microseconds 22.99 microseconds css-color-converter 0.38 microseconds 3.78 ms
for-the-badge SVG with CSS colors npm / v5.0.2 / rgba(...) / hsl(...) / for-the-badge 14.37 microseconds 13.95 microseconds color 0.41 microseconds 4.14 ms
JSON badge payload json / coverage / 95% / papayawhip / #ABC123 0.57 microseconds 1.11 microseconds css-color-converter 0.54 microseconds 5.40 ms

All four end-to-end scenarios produced identical output strings across both implementations. The practical takeaway is that the large microbenchmark gap mostly collapses once full SVG rendering is part of the request path.

Per-badge benchmark payloads
[
  {
    "label": "build",
    "message": "passing",
    "color": "brightgreen",
    "labelColor": "grey",
    "style": "flat"
  },
  {
    "label": "coverage",
    "message": "95%",
    "color": "papayawhip",
    "labelColor": "#ABC123",
    "style": "flat"
  },
  {
    "label": "npm",
    "message": "v5.0.2",
    "color": "rgba(100, 20, 111, 1)",
    "labelColor": "hsl(122, 50%, 22%)",
    "style": "for-the-badge",
    "idSuffix": "bench"
  },
  {
    "format": "json",
    "label": "coverage",
    "message": "95%",
    "color": "papayawhip",
    "labelColor": "#ABC123",
    "links": ["https://example.com"],
    "idSuffix": "bench"
  }
]

Methodology

Scenario Results

Parse valid overlapping CSS inputs

Direct parser cost for formats both libraries understand: hex, named colors, rgb/rgba, hsl/hsla.

Winner: css-color-converter (1.62x faster by median ops/s)

Implementation Median ops/s Median ns/op Mean ops/s Range ops/s
css-color-converter 3,940,541 254 3,937,940 3,900,074 - 3,963,041
color 2,436,991 410 2,436,766 2,425,380 - 2,451,278
css-color-converter
3,940,541
color
2,436,991
Inputs (13)
[
  "#ccc",
  "#fffe",
  "#fffeffff",
  "#ABC123",
  "papayawhip",
  "purple",
  "  blue ",
  "rgb(100%, 200%, 222%)",
  "rgb(122, 200, 222)",
  "rgb(122, 200, 222, 1)",
  "rgba(100, 20, 111, 1)",
  "hsl(122, 50%, 22%)",
  "hsla(122, 50%, 22%, 1)"
]

Parse invalid CSS inputs

Failure-path cost on clearly invalid inputs. css-color-converter returns null; color throws and is caught by the wrapper.

Winner: css-color-converter (35.63x faster by median ops/s)

Implementation Median ops/s Median ns/op Mean ops/s Range ops/s
css-color-converter 7,877,925 127 7,856,756 7,766,009 - 7,940,668
color 221,133 4,522 220,873 219,793 - 221,212
css-color-converter
7,877,925
color
221,133
Inputs (8)
[
  "",
  "not-a-color",
  "#ABCFGH",
  "rgb(100%, 200, 222)",
  "hsl(122, 200, 222, 1)",
  "hsl(122, 200, 222)",
  "hsl(122, 200, 222%)",
  "hwba(122, 200%, 222, 1)"
]

normalizeColor-style mixed badge inputs

Project-level wrapper benchmark with named colors, aliases, hex strings, CSS colors, and invalid inputs mixed together.

Winner: css-color-converter (5.33x faster by median ops/s)

Implementation Median ops/s Median ns/op Mean ops/s Range ops/s
css-color-converter 4,572,875 219 4,569,508 4,546,993 - 4,591,768
color 857,998 1,166 857,892 856,286 - 859,449
css-color-converter
4,572,875
color
857,998
Inputs (22)
[
  "red",
  "blue",
  "lightgray",
  "informational",
  "4c1",
  "f00f00",
  "ABC123",
  "#ccc",
  "#fffe",
  "#fffeffff",
  "#ABC123",
  "papayawhip",
  "purple",
  "  blue ",
  "rgb(100%, 200%, 222%)",
  "rgb(122, 200, 222)",
  "rgba(100, 20, 111, 1)",
  "hsl(122, 50%, 22%)",
  "hsla(122, 50%, 22%, 1)",
  "not-a-color",
  "#ABCFGH",
  "rgb(100%, 200, 222)"
]

brightness() on valid overlapping CSS inputs

Project-level wrapper benchmark for the parse-and-convert-to-RGB path used by brightness().

Winner: css-color-converter (3.20x faster by median ops/s)

Implementation Median ops/s Median ns/op Mean ops/s Range ops/s
css-color-converter 2,896,785 345 2,896,424 2,885,548 - 2,908,803
color 905,245 1,105 895,288 830,574 - 907,915
css-color-converter
2,896,785
color
905,245
Inputs (13)
[
  "#ccc",
  "#fffe",
  "#fffeffff",
  "#ABC123",
  "papayawhip",
  "purple",
  "  blue ",
  "rgb(100%, 200%, 222%)",
  "rgb(122, 200, 222)",
  "rgb(122, 200, 222, 1)",
  "rgba(100, 20, 111, 1)",
  "hsl(122, 50%, 22%)",
  "hsla(122, 50%, 22%, 1)"
]

brightness() on invalid CSS inputs

Failure-path cost for brightness(). This highlights the exception overhead in the color-based implementation.

Winner: css-color-converter (41.48x faster by median ops/s)

Implementation Median ops/s Median ns/op Mean ops/s Range ops/s
css-color-converter 8,961,912 112 8,964,931 8,867,633 - 9,046,437
color 216,053 4,628 214,402 203,833 - 216,628
css-color-converter
8,961,912
color
216,053
Inputs (8)
[
  "",
  "not-a-color",
  "#ABCFGH",
  "rgb(100%, 200, 222)",
  "hsl(122, 200, 222, 1)",
  "hsl(122, 200, 222)",
  "hsl(122, 200, 222%)",
  "hwba(122, 200%, 222, 1)"
]

New Capability Coverage

The migration was not purely about speed. These examples are accepted by the new color-based implementation but not by the previous library.

rgb(-100, 20, 111)

css-color-converter unsupported

color rgb(-100, 20, 111)

rgba(-100, 20, 111, 1.1)

css-color-converter unsupported

color rgba(-100, 20, 111, 1.1)

hwb(122, 200%, 222%)

css-color-converter unsupported

color hwb(122, 100%, 100%)

hwb(122, 200%, 222%, 1)

css-color-converter unsupported

color hwb(122, 100%, 100%)

Interpretation

Raw sample values are summarized in this HTML to keep the report readable.