Swift
UIColor
iOS Development
Color Variations
Mobile App Design

Get lighter and darker color variations for a given UIColor

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Generating lighter and darker variants of a UIColor is a common UI task for pressed states, gradients, and theming. The important detail is that there is no single "correct" notion of lighter or darker; the result depends on which color space you adjust and how you clamp the values.

The Simplest RGB-Based Approach

A practical starting point is to extract the RGB components, adjust them by a percentage, and clamp the results into the valid 0 to 1 range.

swift
1import UIKit
2
3extension UIColor {
4    func adjusted(by percentage: CGFloat) -> UIColor {
5        var red: CGFloat = 0
6        var green: CGFloat = 0
7        var blue: CGFloat = 0
8        var alpha: CGFloat = 0
9
10        guard getRed(&red, green: &green, blue: &blue, alpha: &alpha) else {
11            return self
12        }
13
14        func clamp(_ value: CGFloat) -> CGFloat {
15            min(max(value, 0), 1)
16        }
17
18        return UIColor(
19            red: clamp(red + percentage),
20            green: clamp(green + percentage),
21            blue: clamp(blue + percentage),
22            alpha: alpha
23        )
24    }
25
26    func lighter(by amount: CGFloat = 0.1) -> UIColor {
27        adjusted(by: abs(amount))
28    }
29
30    func darker(by amount: CGFloat = 0.1) -> UIColor {
31        adjusted(by: -abs(amount))
32    }
33}

Usage is simple:

swift
let base = UIColor.systemBlue
let lighter = base.lighter(by: 0.15)
let darker = base.darker(by: 0.15)

This works well for many app-level styling tasks.

Why RGB Adjustment Is Only an Approximation

Adding or subtracting the same amount from red, green, and blue is easy, but it is not perceptually uniform. Some colors shift more naturally than others.

For example:

  • very bright colors can hit the upper clamp quickly
  • very dark colors may collapse toward black too aggressively
  • saturated colors can change character when all channels move equally

That does not make RGB adjustment wrong. It just means it is a practical UI approximation, not a color-science-perfect transform.

A Hue-Saturation-Brightness Alternative

For many design tasks, adjusting brightness in HSB space is more intuitive.

swift
1import UIKit
2
3extension UIColor {
4    func adjustBrightness(by amount: CGFloat) -> UIColor {
5        var hue: CGFloat = 0
6        var saturation: CGFloat = 0
7        var brightness: CGFloat = 0
8        var alpha: CGFloat = 0
9
10        guard getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: &alpha) else {
11            return self
12        }
13
14        let newBrightness = min(max(brightness + amount, 0), 1)
15        return UIColor(hue: hue, saturation: saturation, brightness: newBrightness, alpha: alpha)
16    }
17}

This often gives more visually consistent "lighter" and "darker" results for UI themes, especially when the original color is already strongly saturated.

Dynamic System Colors Need Care

System colors such as UIColor.label or UIColor.systemBackground can change with traits like light mode and dark mode. If you compute a lighter or darker value once and store it statically, you may lose that dynamic behavior.

If the base color is dynamic, consider resolving it in the current trait environment before adjustment or redefining the derived color dynamically too.

Practical Uses

Lighter and darker variants are commonly used for:

  • button highlight states
  • border or shadow accents
  • gradients from one theme color
  • selected versus unselected control styling

The implementation does not need to be mathematically perfect to be useful. It just needs to be consistent and visually acceptable for the app's design system.

Common Pitfalls

The biggest mistake is assuming every UIColor can always provide RGB or HSB components directly. Some colors, especially certain pattern or dynamic colors, may fail component extraction.

Another mistake is pushing component values beyond the valid range without clamping.

A third issue is treating RGB adjustment as perceptually accurate. It is simple and useful, but not colorimetrically precise.

Finally, if you are working with dynamic system colors, be careful not to accidentally freeze a light-mode-derived color and reuse it in dark mode.

Summary

  • A simple way to lighten or darken UIColor is to adjust RGB components and clamp the result.
  • Adjusting brightness in HSB space often produces more natural-looking variants.
  • Dynamic system colors require extra care so trait-based behavior is not lost.
  • Clamp all component values into the valid range.
  • Use the simpler method that matches your design needs rather than over-engineering color math.
  • The goal is usually consistent UI behavior, not perfect color science.

Course illustration
Course illustration

All Rights Reserved.