Skip to content
ColorTokensKitby Penguin Design Ventures
Contents
Function

.lerp(_:t:)

Find the color partway between two others, for your own blends, chart scales or animations.

Updated View as Markdown

Find the color partway between two others with lerp(_:t:), for your own blends, chart scales or animations. It takes the other color and how far to go, from 0 (this color) to 1 (the other), and returns a value of the same type:

swift
let start = OKLCHColor(hex: "#00B386")   // the travel app's brand color, at hue 166.99
let end = Color.proSky._200.toOKLCH()     // Reykjavík's pale sky blue, at hue 230
start.lerp(end, t: 0.5)                   // OKLCHColor(l: 0.772, c: 0.110, h: 198.5), #4BCACF
#00b386
start
#4bcacf
start.lerp(end, t: 0.5)
#a9dbfa
end

Steps for a chart or an animation#

Call it with evenly spaced values of t to get a scale of colors between two ends:

swift
let start = OKLCHColor(hex: "#00B386")
let end = Color.proSky._200.toOKLCH()
let scale = (0...4).map { start.lerp(end, t: Double($0) / 4).toColor() }
#00b386
t: 0
#1ec0ad
t: 0.25
#4bcacf
t: 0.5
#74d4e9
t: 0.75
#9addfd
t: 1

Which space to mix in#

  • OKLCHColor and LCHColor take the short way around the hue wheel, so the middle keeps its chroma.
  • OKLabColor, LABColor, RGBColor and XYZColor mix in a straight line, so the middle can come out grayer. The same pair halfway in OKLab is #64C9C1, where OKLCH gives #4BCACF.

For gradients, use proGradient(), which also keeps colors inside Display P3 and eases between the ends. To mix two tokens and keep dark mode, use blend(with:by:).

How it behaves#

OKLCHColor and LCHColor round t to three decimal places. No type fits the result into Display P3, and alpha is mixed along with the color. Both colors need the same type, so convert one first, as in Color.proSky._200.toOKLCH().

API#

swift
public extension OKLCHColor { func lerp(_ other: OKLCHColor, t: CGFloat) -> OKLCHColor }
public extension OKLabColor { func lerp(_ other: OKLabColor, t: CGFloat) -> OKLabColor }
public extension LCHColor   { func lerp(_ other: LCHColor, t: CGFloat) -> LCHColor }
public extension LABColor   { func lerp(_ other: LABColor, t: CGFloat) -> LABColor }
public extension RGBColor   { func lerp(_ other: RGBColor, t: CGFloat) -> RGBColor }
public extension XYZColor   { func lerp(_ other: XYZColor, t: CGFloat) -> XYZColor }
ParameterTypeWhat it does
othersame typeThe color at t: 1.
tCGFloatHow far to go, from 0 (this color) to 1 (other).

It returns a new value of the same type, t of the way from this color to other.

Sources#

  • The ColorSpace folder, where each type's Interpolation file defines lerp(_:t:).

See also

  • .blend(with:by:) Mix two colors into one that follows dark mode, or fade a color out cleanly.
  • .proGradient() Fill cards and buttons with gradients that stay vivid end to end, in light and dark mode.
  • .toOKLCH() Read a color's lightness, chroma and hue the way the palette sees them, to compare or adjust it.
  • How gradients blend and ease Why plain gradients turn gray, how each blend travels between colors, and where easing puts them.