Mixing colors in SwiftUI and Xcode 16
Published on: June 18, 2024SwiftUI in iOS 18 and macOS 15 has gained a new trick; it can mix colors. This means that it’s now possible to take a color and modify it by applying another color to it using a provided percentage.
The video below shows how this works:
Notice how the large rectangle updates its color to be a certain mix of a left and right color.
In the video I use distinct colors but you can also mix with white or black to lighten or darken your color.
One use of color mixing I like a lot is to explore color palettes. Since you can see which colors “fit” between two distinct colors you get to explore color in a way that, to me, is very inspiring.
If you prefer learning through video over learning through text, here's a video that I made a companion for this post:
Here’s the code that allows you to mix two colors in SwiftUI:
let leftColor = Color.pink
let rightColor = Color.blue
let mix = 0.5
// create a rectangle filled with our mixed color
RoundedRectangle(cornerRadius: 16)
.fill(leftColor.mix(with: rightColor, by: mix, in: .perceptual))
.frame(width: 100, height: 100)
The API is pretty straightforward. You take a color and you call mix
on it. You pass a second color, a mixing value between 0 and 1, and whether you want to interpolate the mixed color in a perceptual color space or using the device color space.
By default, perceptual will be used since that should, in theory, mix colors in a way that makes sense to the human eye and is consistent between different device screens. Mixing based on device color space can yield different results that may or may not be what you’re looking for; I recommend experimenting to see the exact differences.
The mixing value that you provide determines how much of the second color should be mixed into the source color. A value of 0 gets you the original color and a value of 1 replaces the original color entirely with the color you’re mixing in.
If you’re interested in rebuilding the experiment UI from the start of this post, you can grab the code right here:
struct ColorMix: View {
@State private var leftColor = Color.blue
@State private var rightColor = Color.pink
@State private var mix = 0.5
var body: some View {
VStack {
HStack(spacing: 8) {
ColorPicker("Left", selection: $leftColor)
.labelsHidden()
ColorPicker("Right", selection: $rightColor)
.labelsHidden()
}
HStack {
VStack {
RoundedRectangle(cornerRadius: 16)
.fill(leftColor)
.frame(width: 100, height: 100)
Text("\((1 - mix), format: .percent.precision(.fractionLength(0...2)))")
}
VStack {
RoundedRectangle(cornerRadius: 16)
.fill(rightColor)
.frame(width: 100, height: 100)
Text("\(mix, format: .percent.precision(.fractionLength(0...2)))")
}
}
// create a rectangle filled with our mixed color
RoundedRectangle(cornerRadius: 16)
.fill(leftColor.mix(with: rightColor, by: mix, in: .perceptual))
.frame(width: 100, height: 100)
Slider(value: $mix, in: 0...1)
}
}
}