WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit efa0b95

Browse files
committed
Add function to calculate colour contrast ratio
1 parent 32519a6 commit efa0b95

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

dotcom-rendering/src/lib/colour.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { isLight } from './colour';
1+
import { getContrast, isLight } from './colour';
2+
3+
const round = (value: number): number => Math.round(value * 100) / 100;
24

35
describe('isLight', () => {
46
it('should return the correct response for dark hex colours', () => {
@@ -38,3 +40,18 @@ describe('isLight', () => {
3840
expect(isLight('wyx')).toBe(false);
3941
});
4042
});
43+
44+
/**
45+
* Contrast ratio calculated by `getContrast` should match that calculated
46+
* by the WebAIM contrast checker: https://webaim.org/resources/contrastchecker
47+
*/
48+
describe('getContrast', () => {
49+
it('should return the correct contrast ratio for two colours', () => {
50+
expect(round(getContrast('#000', '#fff'))).toEqual(21);
51+
expect(round(getContrast('#f00', '#fff'))).toEqual(4);
52+
expect(round(getContrast('#faa01b', '#f6f6f6'))).toEqual(1.92);
53+
expect(round(getContrast('#2a449a', '#f6f6f6'))).toEqual(8.12);
54+
expect(round(getContrast('#f0c650', '#1a1a1a'))).toEqual(10.69);
55+
expect(round(getContrast('#559861', '#1a1a1a'))).toEqual(5.01);
56+
});
57+
});

dotcom-rendering/src/lib/colour.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,34 @@ const hexToRgb = (
2323
: null;
2424
};
2525

26+
// https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
27+
// Based on: https://github.com/siege-media/contrast-ratio/blob/gh-pages/color.js
28+
const processLuminance = (channel: number): number => {
29+
const scaledChannel = channel / 255;
30+
return scaledChannel <= 0.03928
31+
? scaledChannel / 12.92
32+
: Math.pow((scaledChannel + 0.055) / 1.055, 2.4);
33+
};
34+
35+
const getLuminance = (colour: string): number => {
36+
const rgb = hexToRgb(colour);
37+
if (!rgb) return 0;
38+
return (
39+
processLuminance(rgb.r) * 0.2126 +
40+
processLuminance(rgb.g) * 0.7152 +
41+
processLuminance(rgb.b) * 0.0722
42+
);
43+
};
44+
45+
// http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
46+
export const getContrast = (colour1: string, colour2: string): number => {
47+
const luminance1 = getLuminance(colour1);
48+
const luminance2 = getLuminance(colour2);
49+
const brightest = Math.max(luminance1, luminance2);
50+
const darkest = Math.min(luminance1, luminance2);
51+
return (brightest + 0.05) / (darkest + 0.05);
52+
};
53+
2654
const getBrightness = (colour: string): number => {
2755
// http://www.w3.org/TR/AERT#color-contrast
2856
const rgb = hexToRgb(colour);

0 commit comments

Comments
 (0)