Make one color more vivid for an accent with saturate(by:). It adds chroma at the same lightness, 20% by default, so text on it keeps its contrast, and returns a Color:
let food = Color.proPlum // the Food tag's theme
HStack {
Text("Food")
.padding(8)
.background(food.backgroundTertiary) // _200 in light mode, _700 in dark
Text("Food")
.padding(8)
.background(food.backgroundTertiary.saturate()) // 20% more color, just as light
}
.font(.subheadline)
.foregroundStyle(food.foregroundPrimary)The label measures the same on both tags, because the fill's lightness doesn't move. Push the amount up below: the color gets more vivid until the screen runs out of color, and its lightness stays put:
Color.proBlue._600.toColor().saturate()How far it goes#
Every hue in the palette shares one chroma at each stop, the most that nearly every hue can show, as how the colors were built explains. saturate(by:) goes past that, up to the most Display P3 can show for that hue and lightness, and no further.
On a screen that only shows sRGB, such as many external monitors, the system clips the extra, so a saturated color looks less vivid there.
How it behaves#
The result leaves the palette on purpose, so a design spec can't name it by stop. lighten(by:) and the other stop functions still work on it, and move it by the same visual step instead of snapping.
Gray, white and black have no hue to strengthen, so they come back unchanged. A negative amount takes color out, like desaturate(by:), and at -1 or below you get a gray. The result keeps the color's opacity, and each mode saturates that mode's color.
API#
public extension Color {
func saturate(by amount: Double = 0.2) -> Color
}| Parameter | Type | Default | What other values do |
|---|---|---|---|
amount | Double | 0.2 | The fraction of chroma to add: 0.5 is 50% more. A negative value takes color out. |
It returns a new Color at the same lightness and hue, with more chroma, in each appearance.
Sources#
- Color+Adjustments.swift, which defines
saturate(by:). - ColorAdjustment.swift, which scales chroma and fits the result into Display P3.
See also
- .rotateHue(by:) Make an accent or a whole second theme from your brand color, at the same lightness.
- Fitting colors into Display P3 Stay inside Display P3 without losing contrast: chroma drops, lightness holds.
- What does equal lightness cost? What equal contrast costs, from quieter reds to olive yellows, and what you can do about each.
- Color theory Pair stops that always read, and pick secondary hues that match your brand, in both modes.