Skip to content
ColorTokensKitby Penguin Design Ventures
Contents
Function

.blend(with:by:)

Mix two colors into one that follows dark mode, or fade a color out cleanly.

Updated View as Markdown

Mix two colors into one that follows dark mode with blend(with:by:). It mixes in OKLab, halfway by default, and returns a Color. Mix a little of your brand into a gray card, and the card picks up its hue in both modes:

swift
// Halfway from gray to your brand
let card = Color.backgroundSecondary.blend(with: brand.backgroundSecondary)

Text("Your flight to Lisbon boards at 14:30.")
    .foregroundStyle(brand.foregroundPrimary)
    .padding()
    .frame(maxWidth: .infinity, alignment: .leading)
    .background(card)
light mode
Your flight to Lisbon boards at 14:30.

Each mode mixes its own two colors, so the card is light in light mode and dark in dark mode. Pick two colors and slide the fraction below: 0 is your color and 1 is the other:

Try it / blend()
Color
With
light mode
Before
#4176b8proBlue._600
After
#8d76a4off the palette
dark mode
Before
#4176b8proBlue._600
After
#8d76a4off the palette
swift
Color.proBlue._600.toColor().blend(with: Color.proPink._500.toColor())

Fading out#

Blend with .clear to fade a color without changing it. The mix keeps the color and only lowers its opacity, so brand.backgroundTertiary.blend(with: .clear) is the same color at half opacity, not a grayer one.

Blend or mix(with:by:in:)?#

blend(with:by:) runs on every system the library supports, while SwiftUI's own mix(with:by:in:) needs iOS 18 or macOS 15. We haven't compared their results.

How it behaves#

The result usually lands off the palette, and its contrast depends on the two colors you mix, so check text on it with contrastRatio(to:method:). A mix too vivid for Display P3 gets its chroma lowered at the same lightness.

The fraction is clamped from 0 to 1. Opacity mixes along with the color.

API#

swift
public extension Color {
    func blend(with other: Color, by fraction: Double = 0.5) -> Color
}
ParameterTypeDefaultWhat other values do
otherColornoneThe color to mix toward. With .clear, the mix only fades.
fractionDouble0.5How far toward other, from 0 to 1. Values outside are clamped.

It returns a new Color that mixes the two colors in each appearance.

Sources#

See also

  • .proGradient() Fill cards and buttons with gradients that stay vivid end to end, in light and dark mode.
  • How gradients blend and ease Why plain gradients turn gray, how each blend travels between colors, and where easing puts them.
  • .saturate(by:) Make one color more vivid for an accent, at the same lightness and contrast.
  • Setting up themes Recolor a view, a screen or your whole app from one value, with the same contrast in every hue.