Skip to content
ColorTokensKitby Penguin Design Ventures
Contents
Function

.analogous(count:spread:)

Close neighbors of your color for banners, illustrations and gradients, at matching contrast.

Updated View as Markdown

Fill a banner or an illustration with close neighbors of your color with .analogous(). You get count hues spread apart, centered on yours, all at your color's lightness.

swift
Rectangle()
    .fill(brand._400.analogous().proGradient(from: .leading, to: .trailing))   // 137°, 167° and 197°
    .frame(height: 64)
light mode

Pick your color below and change the count and spread. With the defaults, you get three hues 30° apart.

Try it / Harmonies
Color

Every OKLCH hue at this color's lightness

0°90°180°270°360°
light mode
#25b2e0proCerulean._400
#63a7fdproBlue._400
#979afdproIris._400
dark mode
#25b2e0proCerulean._400
#63a7fdproBlue._400
#979afdproIris._400
swift
let color = Color.proBlue._400.toColor()
color.analogous()

More neighbors, closer together#

Raise count for more colors and lower spread to keep them close. Five hues 15° apart stay within 30° of yours either way:

swift
let neighbors = brand._400.analogous(count: 5, spread: .degrees(15))
#7eb459
137°
#62b872
152°
#44ba8c
167°
#22baa6
182°
#13b8be
197°

Hues around the whole wheel#

A spread of 360° divided by count spaces the colors evenly around the wheel, with yours in the middle of the list. That gives five chart series as far apart as five hues can be:

swift
let series = brand.analogous(count: 5, spread: .degrees(72))   // families at 23°, 95°, 167°, 239° and 311°
#ef847e
23°
#bfa320
95°
#44ba8c
167°
#4dabf5
239°
#c18dee
311°

Using tokens in charts shows which token each series takes.

How it behaves#

The colors come back from the most negative offset to the most positive, so yours sits in the middle: Color.proBlue.analogous() is cerulean, blue and iris. With an even count there is no middle, so your color isn't one of them: analogous(count: 2) gives the hues 15° either side.

A count below 1 counts as 1, which gives your color alone. Each color is turned with rotateHue(by:), so a palette color lands on the same stop at its new hue. On a ProTheme, you get whole families at the stop you started from. Gray has no hue, so its neighbors are all gray.

API#

swift
public extension Color {
    func analogous(count: Int = 3, spread: Angle = .degrees(30)) -> [Color]
}

public extension ProTheme {
    func analogous(count: Int = 3, spread: Angle = .degrees(30)) -> [ProTheme]
}
ParameterTypeDefaultWhat other values do
countInt3How many colors. With an even count, yours isn't one of them. Below 1 counts as 1.
spreadAngle30°The gap between neighbors. 360° divided by count spaces them around the whole wheel.

It returns count colors or families, centered on yours. It's the same as harmony(.analogous(count:spread:)).

Sources#

See also

  • Color theory Pair stops that always read, and pick secondary hues that match your brand, in both modes.
  • .proGradient() Fill cards and buttons with gradients that stay vivid end to end, in light and dark mode.
  • .triad Secondary and tertiary colors for tags and categories, at the same contrast as your brand.
  • Gradient theory Add depth with gradients that stay vivid, from a single color or a recipe, in both modes.