Hue, saturation and lightness address the same colours as RGB in cylindrical coordinates. Darkening a colour changes one component instead of three, which is what palette and theme code uses the model for.
Model
| Item | Value |
|---|---|
| Type string | HSL |
| Enum case | ColorModelType::Hsl |
| Class | \Com\Tecnick\Color\Model\Hsl |
| PDF colour space | DeviceRGB, by conversion |
| Notations | hsl(), hsla() |
Components
| Component | Key | Range | Out of range |
|---|---|---|---|
| Hue | hue | 0.0 to 1.0, a fraction of a full turn | wrapped |
| Saturation | saturation | 0.0 to 1.0 | clamped |
| Lightness | lightness | 0.0 to 1.0 | clamped |
| Alpha | alpha | 0.0 to 1.0, default 1.0 | clamped |
The hue is stored as a fraction, not as degrees. The hsl() notation takes degrees and getCssColor() emits degrees; the constructor does not.
Construction
<?php
require_once __DIR__ . '/vendor/autoload.php';
// hue is a fraction of a full turn: 210 / 360
$hsl = new \Com\Tecnick\Color\Model\Hsl([
'hue' => 210 / 360,
'saturation' => 0.5,
'lightness' => 0.4,
]);
echo $hsl->getCssColor(), "\n";
echo $hsl->getRgbHexColor(), "\n";
hsl(210,50%,40%)
#336699
Output
Every accessor, against #336699:
| Call | Result |
|---|---|
getCssColor() | hsl(210,50%,40%) |
getRgbHexColor() | #336699 |
getRgbaHexColor() | #336699ff |
getComponentsString() | 0.200000 0.400000 0.600000 |
getPdfColor() | 0.200000 0.400000 0.600000 rg |
getPdfColor(true) | 0.200000 0.400000 0.600000 RG |
getJsPdfColor() | ["RGB",0.200000,0.400000,0.600000] |
getArray() | ['H' => 0.5833333333333334, 'S' => 0.49999999999999994, 'L' => 0.4, 'A' => 1.0] |
getNormalizedArray(255) | ['H' => 210.0, 'S' => 0.49999999999999994, 'L' => 0.4, 'A' => 1.0] |
getPDFacArray() | [0.19999999999999996, 0.3999999999999998, 0.6000000000000001] |
getNormalizedArray(255) ignores its argument here. Hue comes back in degrees and saturation and lightness as fractions, since neither is scaled by a reference maximum. The same call on an Rgb object scales all three channels.
PDF has no HSL colour space, so getPdfColor() and getJsPdfColor() convert and emit DeviceRGB.
Wrapping And Clamping
The hue is an angle, so it wraps: 1.25 turns is the same direction as 0.25. Saturation and lightness are magnitudes, so they clamp.
// hue wraps
foreach ([210 / 360, 570 / 360, -150 / 360, 2.0] as $hue) {
$hsl = new \Com\Tecnick\Color\Model\Hsl([
'hue' => $hue,
'saturation' => 0.5,
'lightness' => 0.4,
]);
printf("%9.6f %s\n", $hue, $hsl->getCssColor());
}
// saturation and lightness clamp
echo (new \Com\Tecnick\Color\Model\Hsl([
'hue' => 0.5,
'saturation' => 2.0,
'lightness' => -1.0,
]))->getCssColor(), "\n";
0.583333 hsl(210,50%,40%)
1.583333 hsl(210,50%,40%)
-0.416667 hsl(210,50%,40%)
2.000000 hsl(0,50%,40%)
hsl(180,100%,0%)
Percentages
The CSS specification defines saturation and lightness as percentages, and the parser follows it whether or not the % is written. hsl(210,50,40) is the same colour as hsl(210,50%,40%). Nothing raises, so hsl(210,0.5,0.4) is read as a saturation of half a percent.
See Also
- tc-lib-color : the library overview.
- Colour Models : the five side by side.
- RGB : the same colours in channels.
- Notations : hue angle units and the separator rules.
- API reference : the generated class documentation.