oklch-smooth

A smooth, full spectrum sRGB colour palette for data visualisation.

The colour palette covers 16 hues, with nine shades in each group. An additional group of neutral greys complete the set, for a total of 153 colours. The palette is designed to produce smooth curves across each component of the OKLCH colour model. The wide selection of colours is especially useful for visualising complex data across multiple dimensions.

A
A10
#fce9ec
A20
#ffd2da
A30
#ffb7c5
A40
#ff93ab
A50
#fc6e91
A60
#e74b77
A70
#be2f5c
A80
#911541
A90
#5a0023
0
0
0
0
0
0
B
B10
#fde9e7
B20
#fed4d0
B30
#ffb9b4
B40
#ff9793
B50
#ff6c6f
B60
#ed4752
B70
#c7263a
B80
#970823
B90
#5c0010
0
0
0
0
0
0
C
C10
#feeae3
C20
#ffd4c4
C30
#ffbba1
C40
#ff9b76
C50
#fc784a
C60
#e45729
C70
#be3c0f
C80
#8e2500
C90
#551400
0
0
0
0
0
0
D
D10
#ffecdb
D20
#ffdcb9
D30
#ffc587
D40
#ffaa4a
D50
#fa9016
D60
#e17900
D70
#b66000
D80
#7d4200
D90
#472500
0
0
0
0
0
0
E
E10
#feedc6
E20
#ffe197
E30
#ffd158
E40
#fdc215
E50
#edaf00
E60
#cb9300
E70
#9e7100
E80
#6d4d00
E90
#3d2a00
0
0
0
0
0
0
F
F10
#eef2d4
F20
#e3ed9f
F30
#d4e360
F40
#c1d126
F50
#aab900
F60
#8e9b00
F70
#6f7900
F80
#4f5600
F90
#2d3100
0
0
0
0
0
0
G
G10
#e1f5d8
G20
#caf1b9
G30
#a7e788
G40
#87d65d
G50
#6dbe3d
G60
#57a126
G70
#418014
G80
#2d5c0a
G90
#163700
0
0
0
0
0
0
H
H10
#e0f5e5
H20
#c5eecf
H30
#96e4ad
H40
#5ed78a
H50
#2ec06d
H60
#1ca25a
H70
#148046
H80
#105d32
H90
#07371c
0
0
0
0
0
0
I
I10
#d9f6ed
I20
#b7eede
I30
#78e5c9
I40
#33d6b3
I50
#00bc9a
I60
#169e81
I70
#0b7e66
I80
#065b49
I90
#00372b
0
0
0
0
0
0
J
J10
#d7f5f6
J20
#b0eef0
J30
#70e3e8
J40
#33d1d8
J50
#1db8bf
J60
#0f9aa1
J70
#0a7a80
J80
#05595e
J90
#003538
0
0
0
0
0
0
K
K10
#daf4ff
K20
#b9eafe
K30
#84dcfe
K40
#4dcbf6
K50
#09b5e3
K60
#069ac2
K70
#077a9b
K80
#065871
K90
#003344
0
0
0
0
0
0
L
L10
#e3f1fe
L20
#c3e3ff
L30
#9fd4ff
L40
#6fc1ff
L50
#3aadfc
L60
#0391e6
L70
#0073c1
L80
#005391
L90
#002f56
0
0
0
0
0
0
M
M10
#e8eeff
M20
#d7e1fe
M30
#bdcefe
M40
#a0b8ff
M50
#7f9dff
M60
#6381f8
M70
#4a62d4
M80
#32449c
M90
#1e2959
0
0
0
0
0
0
N
N10
#f1ebff
N20
#e6dbff
N30
#d7c5fe
N40
#c6a9ff
N50
#b48aff
N60
#9c6bed
N70
#7f50ca
N80
#5d3996
N90
#361c5c
0
0
0
0
0
0
O
O10
#fce7fc
O20
#fbd1fb
O30
#f9b1fb
O40
#f190f5
O50
#e171e7
O60
#c458cb
O70
#a13da7
O80
#79237f
O90
#4c0452
0
0
0
0
0
0
P
P10
#fee8f2
P20
#fcd3e6
P30
#ffb4d9
P40
#ff8ac8
P50
#f668b6
P60
#dc4d9e
P70
#b82f7f
P80
#8c145d
P90
#580037
0
0
0
0
0
0
Z
Z10
#eaf0f5
Z20
#d8e1e9
Z30
#c1cdd8
Z40
#a9b8c6
Z50
#8fa1b2
Z60
#74889b
Z70
#5b6c7c
Z80
#414e5a
Z90
#262f37
0
0
0
0
0
0

Each hue group follows a consistent lightness profile, with a gradually accelerating descent towards darker shades. This is shown in the first graph following each hue group. The rate of change is most exaggerated in groups D and E. For these groups, the lighter midtones and hue shift help maintain smooth chroma curves and avoid muddy tints and shades.

The minimum and maximum lightness values are designed to work against pure white and off-blacks. This is because many “dark mode” interfaces do not use pure black backgrounds. Using a minimum lightness of 30% (0.3) for the darkest shades leaves sufficient space for a visually distinct off-black background. While 30% may seem large, OKLCH uses a D65 whitepoint, so dark shades stretch over a large part of the colour space.

In each hue, the chroma channel follows a similar parametric curve. The maximum amplitude of the chroma channel is capped at around 20% (0.2) for the pink–red range. The sRGB gamut restricts the chroma most dramatically in the green–blue hues. Intermediate colours use chroma levels that interpolate between these two extremes.

Hues divide the circle into approximately equal rotations. The rotational variation of each group is minimised as much as possible within the limitations of the sRGB gamut. The hue graph for each group shows the amount of deviation from the average within a band of ±10°. The deviation is most pronounced in groups D, E and L to maintain a smooth chroma curve.

Rather than use descriptive names for each group, colours are allocated alphanumeric codes. The letter corresponds to the hue rotation, the number to lightness. The aim here is to facilitate quick comparisons. For example, it is easy to assess adjacency when comparing codes — A20 and B20 are adjacent, but H60 and J60 skip over I60. The alphanumeric codes also allow for terser names when applied as CSS classes.

The nine shades have sufficient contrast between values when adjacent colours are absolutely required. The odd number also simplifies the process of selecting a central colour for each hue. However, the default values use 10 — not 100 — as the base. This still allows room for intermediate colours, but again allows for terser class names.

The palette can be used as a drop-in replacement for the default Tailwind CSS framework colours using the following configuration.

/** @type {import("tailwindcss").Config} */
module.exports = {
  theme: {
    colors: {
      /* See https://www.s-ings.com/scratchpad/oklch-smooth/ */
      A: [{10: "#fce9ec"}, {20: "#ffd2da"}, {30: "#ffb7c5"}, {40: "#ff93ab"}, {50: "#fc6e91"}, {60: "#e74b77"}, {70: "#be2f5c"}, {80: "#911541"}, {90: "#5a0023"}],
      B: [{10: "#fde9e7"}, {20: "#fed4d0"}, {30: "#ffb9b4"}, {40: "#ff9793"}, {50: "#ff6c6f"}, {60: "#ed4752"}, {70: "#c7263a"}, {80: "#970823"}, {90: "#5c0010"}],
      C: [{10: "#feeae3"}, {20: "#ffd4c4"}, {30: "#ffbba1"}, {40: "#ff9b76"}, {50: "#fc784a"}, {60: "#e45729"}, {70: "#be3c0f"}, {80: "#8e2500"}, {90: "#551400"}],
      D: [{10: "#ffecdb"}, {20: "#ffdcb9"}, {30: "#ffc587"}, {40: "#ffaa4a"}, {50: "#fa9016"}, {60: "#e17900"}, {70: "#b66000"}, {80: "#7d4200"}, {90: "#472500"}],
      E: [{10: "#feedc6"}, {20: "#ffe197"}, {30: "#ffd158"}, {40: "#fdc215"}, {50: "#edaf00"}, {60: "#cb9300"}, {70: "#9e7100"}, {80: "#6d4d00"}, {90: "#3d2a00"}],
      F: [{10: "#eef2d4"}, {20: "#e3ed9f"}, {30: "#d4e360"}, {40: "#c1d126"}, {50: "#aab900"}, {60: "#8e9b00"}, {70: "#6f7900"}, {80: "#4f5600"}, {90: "#2d3100"}],
      G: [{10: "#e1f5d8"}, {20: "#caf1b9"}, {30: "#a7e788"}, {40: "#87d65d"}, {50: "#6dbe3d"}, {60: "#57a126"}, {70: "#418014"}, {80: "#2d5c0a"}, {90: "#163700"}],
      H: [{10: "#e0f5e5"}, {20: "#c5eecf"}, {30: "#96e4ad"}, {40: "#5ed78a"}, {50: "#2ec06d"}, {60: "#1ca25a"}, {70: "#148046"}, {80: "#105d32"}, {90: "#07371c"}],
      I: [{10: "#d9f6ed"}, {20: "#b7eede"}, {30: "#78e5c9"}, {40: "#33d6b3"}, {50: "#00bc9a"}, {60: "#169e81"}, {70: "#0b7e66"}, {80: "#065b49"}, {90: "#00372b"}],
      J: [{10: "#d7f5f6"}, {20: "#b0eef0"}, {30: "#70e3e8"}, {40: "#33d1d8"}, {50: "#1db8bf"}, {60: "#0f9aa1"}, {70: "#0a7a80"}, {80: "#05595e"}, {90: "#003538"}],
      K: [{10: "#daf4ff"}, {20: "#b9eafe"}, {30: "#84dcfe"}, {40: "#4dcbf6"}, {50: "#09b5e3"}, {60: "#069ac2"}, {70: "#077a9b"}, {80: "#065871"}, {90: "#003344"}],
      L: [{10: "#e3f1fe"}, {20: "#c3e3ff"}, {30: "#9fd4ff"}, {40: "#6fc1ff"}, {50: "#3aadfc"}, {60: "#0391e6"}, {70: "#0073c1"}, {80: "#005391"}, {90: "#002f56"}],
      M: [{10: "#e8eeff"}, {20: "#d7e1fe"}, {30: "#bdcefe"}, {40: "#a0b8ff"}, {50: "#7f9dff"}, {60: "#6381f8"}, {70: "#4a62d4"}, {80: "#32449c"}, {90: "#1e2959"}],
      N: [{10: "#f1ebff"}, {20: "#e6dbff"}, {30: "#d7c5fe"}, {40: "#c6a9ff"}, {50: "#b48aff"}, {60: "#9c6bed"}, {70: "#7f50ca"}, {80: "#5d3996"}, {90: "#361c5c"}],
      O: [{10: "#fce7fc"}, {20: "#fbd1fb"}, {30: "#f9b1fb"}, {40: "#f190f5"}, {50: "#e171e7"}, {60: "#c458cb"}, {70: "#a13da7"}, {80: "#79237f"}, {90: "#4c0452"}],
      P: [{10: "#fee8f2"}, {20: "#fcd3e6"}, {30: "#ffb4d9"}, {40: "#ff8ac8"}, {50: "#f668b6"}, {60: "#dc4d9e"}, {70: "#b82f7f"}, {80: "#8c145d"}, {90: "#580037"}],
      Z: [{10: "#eaf0f5"}, {20: "#d8e1e9"}, {30: "#c1cdd8"}, {40: "#a9b8c6"}, {50: "#8fa1b2"}, {60: "#74889b"}, {70: "#5b6c7c"}, {80: "#414e5a"}, {90: "#262f37"}]
    }
  }
}