GenomeJS
Utilities

contrastRatio()

Calculate the contrast ratio between two hexadecimal colors.

contrastRatio() calculates the contrast ratio between two hexadecimal colors.

It uses relative luminance and returns a numeric ratio.

Import

import { contrastRatio } from "@genomejs/core";

Signature

contrastRatio(
  hexA: string,
  hexB: string,
): number

Parameters

ParameterTypeDescription
hexAstringFirst hexadecimal color
hexBstringSecond hexadecimal color

Use standard six-digit RGB hexadecimal colors:

#000000
#ffffff
#7c6cff

The leading # is accepted.

Return value

number;

The result ranges from approximately:

1

for identical colors, through:

21

for black and white.

Basic example

import { contrastRatio } from "@genomejs/core";

const ratio = contrastRatio("#000000", "#ffffff");

console.log(ratio);
// 21

Similar colors

const ratio = contrastRatio("#777777", "#888888");

console.log(ratio);
// A low contrast ratio

The order of the colors does not affect the result:

contrastRatio("#000000", "#ffffff");

contrastRatio("#ffffff", "#000000");

Both calls return the same ratio.

Use inside a token

import { contrastRatio, Genome } from "@genomejs/core";

const genome = new Genome({
  primitives: {
    foreground: "#ffffff",
    background: "#121620",
  },

  tokens: {
    foregroundContrast: (dna) =>
      contrastRatio(String(dna.foreground), String(dna.background)),
  },
});

Read the result:

genome.getTrait("foregroundContrast");

Because Genome primitives and tokens support strings and numbers, the numeric ratio can be stored as a resolved token.

Check a threshold

const ratio = contrastRatio(foreground, background);

const passes = ratio >= 4.5;

The threshold your application requires depends on the content, size, weight, and accessibility standard you are applying. GenomeJS calculates the ratio; it does not determine the semantic role of the text or UI element.

Create an accessibility report

const pairs = [
  {
    name: "Body text",
    foreground: "#171923",
    background: "#ffffff",
  },
  {
    name: "Muted text",
    foreground: "#667085",
    background: "#ffffff",
  },
];

const report = pairs.map((pair) => ({
  ...pair,

  ratio: contrastRatio(pair.foreground, pair.background),
}));

console.table(report);

Input format

The current implementation parses RGB hexadecimal strings directly.

Use:

contrastRatio("#7c6cff", "#121620");

Avoid unsupported formats such as:

contrastRatio("rgb(124 108 255)", "#121620");
contrastRatio("rebeccapurple", "white");
contrastRatio("#fff", "#000");

The current utility does not normalize CSS color names, RGB functions, HSL functions, alpha channels, or short three-digit hex values.

Invalid values

The current implementation does not explicitly validate its input strings.

Invalid values may produce an incorrect result or NaN rather than a descriptive GenomeJS error.

Validate user-provided colors before passing them to the utility.

function isSixDigitHex(value: string): boolean {
  return /^#[0-9a-f]{6}$/i.test(value);
}
if (!isSixDigitHex(foreground) || !isSixDigitHex(background)) {
  throw new Error("Expected six-digit hexadecimal colors.");
}

const ratio = contrastRatio(foreground, background);

Alpha transparency

The utility does not composite transparent colors against a background.

Resolve transparency before calculating contrast.

For example, a partially transparent foreground may produce different visible colors depending on the surface beneath it.

Relationship to lockContrast()

contrastRatio() measures a pair:

const ratio = contrastRatio(foreground, background);

lockContrast() attempts to adjust the foreground toward a requested minimum:

const adjusted = lockContrast(foreground, background, 4.5);

Use contrastRatio() when you need measurement or reporting.

Use lockContrast() when a derived token should adjust itself automatically.

Error behavior

contrastRatio() does not currently throw a dedicated GenomeJS error for malformed color strings.

Possible problems include:

  • Unsupported color formats
  • Three- or eight-digit hexadecimal values
  • Alpha transparency
  • Invalid hexadecimal characters
  • Empty strings

Validate external input before calling it.

Notes

  • The return value is a number.
  • Color order does not affect the result.
  • The implementation uses relative luminance.
  • Use six-digit RGB hexadecimal input.
  • The utility does not validate color syntax.
  • It does not account for alpha composition.
  • It can be used independently of a Genome instance.

On this page