Choose the generator from the relationship the scale must express. Tints and shades move toward fixed endpoints, a lightness scale samples one perceptual channel, and interpolation connects two arbitrary colors.
Match the generator to the system
| Required relationship | Generator | Main control |
|---|---|---|
| Source to white | tints() |
Oklab mix ratio |
| Source to black | shades() |
Oklab mix ratio |
| Fixed hue and chroma across lightness | lightnessScale() |
Oklch lightness range |
| Two arbitrary endpoints | interpolate() |
Endpoints and interpolation space |
These generators create ordered scales. They do not assign semantic token names or guarantee contrast between adjacent positions.
Generate tints and shades
use PhpColor\Color\Color;
use PhpColor\Color\Palette\ColorPalette;
$base = Color::parse('#3b82f6');
$tints = ColorPalette::tints($base, steps: 5);
$shades = ColorPalette::shades($base, steps: 5);
echo $tints->get(0)->toHex();
echo $tints->get(4)->toHex();
echo $shades->get(4)->toHex();
use PhpColor\Color\Color;
use PhpColor\Color\Palette\ColorPalette;
$base = Color::parse('#3b82f6');
$tints = ColorPalette::tints($base, steps: 5);
$shades = ColorPalette::shades($base, steps: 5);
echo $tints->get(0)->toHex();
echo $tints->get(4)->toHex();
echo $shades->get(4)->toHex();
The tint scale starts at the base and ends at white. The shade scale starts at the base and ends at black. Generation uses the color's Oklab-based tint() and shade() methods.
steps must be at least one. With one step, the palette contains only the original color.
Generate a lightness scale
lightnessScale() holds Oklch chroma, hue, and alpha constant while sampling a lightness range:
use PhpColor\Color\Color;
use PhpColor\Color\Palette\ColorPalette;
$scale = ColorPalette::lightnessScale(
Color::parse('#3b82f6'),
steps: 7,
min: 0.2,
max: 0.85,
);
echo $scale->get(0)->toCss();
echo $scale->get(6)->toCss();
use PhpColor\Color\Color;
use PhpColor\Color\Palette\ColorPalette;
$scale = ColorPalette::lightnessScale(
Color::parse('#3b82f6'),
steps: 7,
min: 0.2,
max: 0.85,
);
echo $scale->get(0)->toCss();
echo $scale->get(6)->toCss();
The returned colors are OklchColor objects. The first has lightness near 0.2; the last has lightness near 0.85. At least one step is required. With one step, the method uses min.
The method does not validate that min is less than max, and Oklch construction clamps lightness to 0..1. Validate a dynamic range before generating a scale.
Interpolate between endpoints
use PhpColor\Color\Color;
use PhpColor\Color\Palette\ColorPalette;
$ramp = ColorPalette::interpolate(
Color::parse('#ff0000'),
Color::parse('#0000ff'),
steps: 7,
);
echo $ramp->count();
echo $ramp->get(0)->toHex();
echo $ramp->get(6)->toHex();
use PhpColor\Color\Color;
use PhpColor\Color\Palette\ColorPalette;
$ramp = ColorPalette::interpolate(
Color::parse('#ff0000'),
Color::parse('#0000ff'),
steps: 7,
);
echo $ramp->count();
echo $ramp->get(0)->toHex();
echo $ramp->get(6)->toHex();
The palette contains seven colors including both endpoints. Oklab is the default interpolation space.
Pass srgb for linear-light sRGB interpolation:
use PhpColor\Color\Color;
use PhpColor\Color\Palette\ColorPalette;
$ramp = ColorPalette::interpolate(
Color::red(),
Color::blue(),
steps: 7,
space: 'srgb',
);
use PhpColor\Color\Color;
use PhpColor\Color\Palette\ColorPalette;
$ramp = ColorPalette::interpolate(
Color::red(),
Color::blue(),
steps: 7,
space: 'srgb',
);
Interpolation requires at least two steps. The supported spaces are the same as Color::mix(): oklab and srgb.
Verify the system, not only the endpoints
The requested number of stops determines sampling positions, not perceptual or contrast thresholds. Inspect all generated colors in the delivery gamut and test the pairs your interface actually uses.
Use a named palette after generation when positions become stable application tokens. Continue with Use collections and scales, Create a seven-step OKLCH scale, or Build controlled color scales.