Keep the parsed color object in its native space until an operation or consumer requires another representation. Convert for a declared purpose, and serialize only at the boundary where a string is required.
Separate four decisions
Normalization is not one automatic conversion. It combines decisions that can occur at different boundaries:
| Boundary | Decision | Useful default |
|---|---|---|
| Acceptance | Is the text a supported concrete color? | Parse into a typed object |
| Processing | Which coordinates suit the operation? | Convert only for that operation |
| Storage or exchange | What schema does the consumer require? | Preserve the native space when the schema supports it |
| CSS delivery | Which browsers or systems consume the value? | Emit the required fallback and wide-gamut value separately |
Converting every input to hexadecimal at acceptance combines all four decisions and makes the narrowest representation the default.
Preserve the native space when it matters
Native CSS serialization can retain a supported wide-gamut space across a parse and format round trip:
use PhpColor\Color\Color;
$input = 'color(display-p3 0.92 0.18 0.12 / 0.8)';
$color = Color::parse($input);
$stored = $color->toCss();
$restored = Color::parse($stored);
echo $color::getSpaceName().PHP_EOL;
echo $stored.PHP_EOL;
echo $restored::getSpaceName().PHP_EOL;
echo $restored->getAlpha().PHP_EOL;
use PhpColor\Color\Color;
$input = 'color(display-p3 0.92 0.18 0.12 / 0.8)';
$color = Color::parse($input);
$stored = $color->toCss();
$restored = Color::parse($stored);
echo $color::getSpaceName().PHP_EOL;
echo $stored.PHP_EOL;
echo $restored::getSpaceName().PHP_EOL;
echo $restored->getAlpha().PHP_EOL;
The output is:
display-p3
color(display-p3 0.92 0.18 0.12 / 0.8)
display-p3
0.8
display-p3
color(display-p3 0.92 0.18 0.12 / 0.8)
display-p3
0.8
This preserves the space name and the displayed coordinates for this value. It does not establish that every formatted decimal string is a lossless persistence format.
Convert when a consumer defines the target
A consumer may require one fixed schema. Convert explicitly before formatting so the reason for normalization remains visible:
use PhpColor\Color\Color;
$source = Color::parse('oklch(0.65 0.18 264)');
$working = $source->to('oklch');
$cssFallback = $source->to('srgb')->toCss();
echo $working::getSpaceName().PHP_EOL;
echo $cssFallback.PHP_EOL;
use PhpColor\Color\Color;
$source = Color::parse('oklch(0.65 0.18 264)');
$working = $source->to('oklch');
$cssFallback = $source->to('srgb')->toCss();
echo $working::getSpaceName().PHP_EOL;
echo $cssFallback.PHP_EOL;
The output is:
oklch
rgb(85 136 251)
oklch
rgb(85 136 251)
Use Oklch when the next operation needs lightness, chroma, and hue coordinates. Use sRGB when a conventional CSS consumer requires RGB. The target system and operation should choose the representation.
Treat compact formats as deliberate reductions
toHex() always converts through sRGB, clamps channels to the byte range, and rounds them to eight-bit values. A Display P3, Rec. 2020, Lab, or Oklch input therefore cannot retain its original coordinates in hexadecimal.
Native CSS formatters also round decimal output. If stored values must survive a material comparison, serialize them, parse them again, and repeat that comparison on the restored value. Do not assume that an internal result and its displayed string have identical precision.
Keep neighboring decisions in their own guides
This page owns where normalization happens, not the details of every target:
- Choose a color space compares working spaces.
- Format CSS colors covers native and selected CSS syntax.
- Precision and gamut explains decimal output, sRGB reduction, and Display P3 delivery.
- Generate hexadecimal output documents byte rounding and alpha order.
Use a Recipe for a specific import or token-file procedure. Use this decision model when designing the boundary that those tasks implement.
Continue
- Normalize mixed color input shows heterogeneous values becoming one declared representation.
- Preserve Display P3 in a stored CSS token verifies one native-space round trip.
ColorInterfacedocuments conversion, CSS formatting, hexadecimal output, channels, and alpha.