# .lighten(by:)

Add highlights and lighter steps to any color, landing on an exact palette stop.

Add a highlight or a lighter step to any color with `lighten(by:)`. It moves the color up the palette by whole stops, one by default, and returns a `Color` that still follows dark mode:

```swift
let fill = brand.backgroundTertiary   // _200 in light mode, _700 in dark

Text("Booked")
    .font(.headline)
    .padding(.vertical, 10)
    .padding(.horizontal, 16)
    .foregroundStyle(brand.foregroundPrimary)
    .background([fill.lighten(), fill].proGradient())   // tops out at _150 in light, _650 in dark
```

What this draws, with `#00B386`:

| Color                | light mode                            | dark mode                              |
| -------------------- | ------------------------------------- | -------------------------------------- |
| `_150/_650`          | #b9ead5                               | color(display-p3 0.1368 0.4655 0.3425) |
| `backgroundTertiary` | #9ce2c5                               | color(display-p3 0.1149 0.4143 0.3028) |
| `foregroundPrimary`  | color(display-p3 0.0176 0.1298 0.086) | #eaf8f2                                |

It draws a linear gradient from `_150/_650` to `backgroundTertiary`, with `.vivid` and `.smooth`.

Light falls from above in both modes, so the top edge is one stop lighter in each. Pick a color and a number of stops below. A palette color lands on an exact stop, and the panel names it:

A playground applies `lighten()` to a palette stop, a token or a hex color. By default it shows `Color.proBlue._600.toColor().lighten()`, which gives #4882ca in both modes. [Try it on the live page](https://colortokenskit.com/api/lighten/).

With the defaults, `proBlue._600` lightens to exactly `proBlue._550`.

## Lighter in both modes

`lighten()` goes lighter in light mode and in dark mode. Lighter text is quieter on a white page but louder on a black one, so for quieter text use [`soften(by:)`](https://colortokenskit.com/api/soften/index.md), which moves toward the page in each mode:

```swift
let lighter = brand.foregroundSecondary.lighten(by: 2)   // _700 in light mode, _100 in dark
let softer = brand.foregroundSecondary.soften(by: 2)     // _700 in light mode, _300 in dark

VStack(alignment: .leading, spacing: 4) {
    Text("3 nights from October 12").foregroundStyle(lighter)   // louder in dark mode
    Text("3 nights from October 12").foregroundStyle(softer)    // quieter in both
}
.font(.subheadline)
```

What this draws, with `#00B386`:

| Color       | light mode                             | dark mode |
| ----------- | -------------------------------------- | --------- |
| `_700/_100` | color(display-p3 0.1149 0.4143 0.3028) | #d2f1e3   |
| `_700/_300` | color(display-p3 0.1149 0.4143 0.3028) | #4cd2a5   |

## Colors off the palette

Step both colors below. `proBlue._600` lands on each stop in turn, while #3C80C4, which sits between stops, moves by the same step in lightness and keeps its hue:

The live page lightens a palette color and a nearby off-palette color step by step. `Color.proBlue._600` lightens to exactly `proBlue._550` (#4882ca); #3C80C4, which sits between stops, lightens to #498cd1. [Try it on the live page](https://colortokenskit.com/api/lighten/).

So a system color or your own hex color lightens by the same visual step as a palette color, without jumping onto the nearest stop.

## How it behaves

A palette color lands on an exact stop of its family, so it has that stop's contrast in every hue. Past `_50` it stays at `_50`, and white stays white. Gray moves along gray's own stops.

A color off the palette keeps its hue and chroma as it gets lighter, as much as Display P3 can show. [Fitting colors into Display P3](https://colortokenskit.com/under-the-hood/gamut-mapping/index.md) explains the limit. The result keeps the color's opacity, and each mode lightens that mode's color.

## API

```swift
public extension Color {
    func lighten(by stops: Int = 1) -> Color
}
```

| Parameter | Type  | Default | What other values do                                                   |
| --------- | ----- | ------- | ---------------------------------------------------------------------- |
| `stops`   | `Int` | `1`     | A negative value goes darker, so `lighten(by: -2)` is `darken(by: 2)`. |

It returns a new `Color` that resolves in each appearance, so it follows light and dark mode like the color you started from.

## Sources

- [Color+Adjustments.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Adjustments/Color+Adjustments.swift), which defines `lighten(by:)`.
- [ColorAdjustment.swift](https://github.com/metasidd/ColorTokensKit-Swift/blob/main/Sources/ColorTokensKit/Adjustments/ColorAdjustment.swift), which moves a color along the stops.

## See also

- [.darken(by:)](https://colortokenskit.com/api/darken/index.md): Make hover and pressed fills from any color, an exact stop darker in both modes.
- [.strengthen(by:)](https://colortokenskit.com/api/strengthen/index.md): Make any token stand out more: darker in light mode, lighter in dark mode.
- [Stops: .\_50 to .\_1000](https://colortokenskit.com/api/stops/index.md): Twenty fixed colors per theme, lightest to darkest, with the same contrast in every hue.
- [How colors land on exact stops](https://colortokenskit.com/under-the-hood/palette-snapping/index.md): Derived colors land on exact stops, so you know their contrast before you run the app.

---

From ColorTokensKit, by Penguin Design Ventures: https://colortokenskit.com/api/lighten/ (updated September 26, 2026).
