The RGB color format is used extensively by developers and designers alike, and it is based on the notion that colors can be represented as a combination of red, green and blue.
Most devices in use today (phones, TVs, laptops) use RGB as an output format. The whole range of available colors can be expressed by varying the value of each color component (red, green or blue) from 0 to 255.
RGB is also a convenient format for storing color information in memory. Each color component only takes up one byte and an ARGB color can be espressed as 4 bytes in memory (using an extra byte for the alpha value).
For example, the red color can be expressed like this in Dart:
// these three expressions all yield exactly the same color
// each component can range from 0 to 255
Color.fromARGB(255, 255, 0, 0);
// same as above, but rather than alpha we use opacity that goes from 0.0 to 1.0
Color.fromRGBO(255, 0, 0, 1.0);
// color in hex format: AARRGGBB
Color(0xFFFF0000);
While RGB makes sense as a storage and output format, it doesn't correspond with the way humans perceive colors.
Instead, there is a more intuitive format that makes a lot more sense when designing mobile and web apps.
Enter HSL
The HSL format represents colors as hue, saturation, and lightness. If you've used a design tool such as Photoshop or Figma, you're probably familiar with this:
In this example, the red color is selected and the picker shows the following values:
- HEX: #FF0000
- H: 360
- S: 100
- L: 50
- Alpha: 100
The most important component is the hue. It starts and ends with the same red color (0 or 360 degrees), and it sweeps across the entire color range:
The saturation represents the vividness of the color and is represented in percentage points. When saturation is at 0%, the hue is meaningless and we can only express grayscales.
The lightness goes from 0 (black) to 100 (white), while a value of 50% represents a full, bright color.
What's great about this format is that it's very intuitive to use:
- Pick the hue, set the saturation to 100, and lightness to 50
- Want a darker shade of a color? Decrease the lightness.
- Want a lighter one? Increase the lightness.
- Color is too "bright" (saturated)? Decrease the saturation.
But there is more. Given any color in HSL format, you can very easily generate a color palette:
You can use this technique to create a palette for the primary, secondary, and accent colors in your app theme. This will make your app or website look more consistent and professional.
Enough theory for now. Time to see how to use HSL in Dart & Flutter! 💙
Colors in Flutter
If you've customized any colors in your Flutter apps, you've probably used the Color class.
And because Flutter closely follows the Material Design spec, it comes with a predefined set of color palettes or swatches.
This indexing system works as long as you want to use the predefined swatches. But if you want to create your own palette with anything other than the default colors, or if you don't want to use Material Design, you've got more work to do.
And as we have seen, RGB is not very intuitive.
The HSLColor class
To represent colors in HSL format, Dart uses a class called HSLColor.
So let's revisit our palette and see how we can define it in Flutter:
final redHSLColors = [
HSLColor.fromAHSL(1, 360, 1.0, 0.25),
HSLColor.fromAHSL(1, 360, 1.0, 0.37),
HSLColor.fromAHSL(1, 360, 1.0, 0.5),
HSLColor.fromAHSL(1, 360, 1.0, 0.63),
HSLColor.fromAHSL(1, 360, 1.0, 0.75),
];
final greenHSLColors = [
HSLColor.fromAHSL(1, 120, 1.0, 0.25),
HSLColor.fromAHSL(1, 120, 1.0, 0.37),
HSLColor.fromAHSL(1, 120, 1.0, 0.5),
HSLColor.fromAHSL(1, 120, 1.0, 0.63),
HSLColor.fromAHSL(1, 120, 1.0, 0.75),
];
final orangeHSLColors = [
HSLColor.fromAHSL(1, 30, 1.0, 0.25),
HSLColor.fromAHSL(1, 30, 1.0, 0.37),
HSLColor.fromAHSL(1, 30, 1.0, 0.5),
HSLColor.fromAHSL(1, 30, 1.0, 0.63),
HSLColor.fromAHSL(1, 30, 1.0, 0.75),
];
This couldn't be any easier. But keep in mind that the values in the lists above have type HSLColor
, and not Color
.
This means that they can't be assigned directly as colors to widget properties:
Container(
// The argument type 'HSLColor' can't be assigned to the parameter type 'Color?'
color: redHSLColors[2],
)
Instead, HSL colors need to be converted back to Color
:
Container(
color: redHSLColors[2].toColor(),
)
In addition to
HSLColor
, the Flutter SDK also defines an HSVColor class, which is very closely related. This article on Wikipedia covers HSL and HSV in more detail.
Wrap Up
We have learned what HSL is and why it is more intuitive than RGB.
But which format should you use for your Flutter apps?
- if you're happy with the predefined Material Design colors, use the existing color swatches (e.g.
Colors.orange
,Colors.red[600]
,Colors.green[400]
). - if your designs use RGB, keep that (most design-to-code tools are still likely to export to RGB).
- if you need custom colors with different shades, HSL is easier to use.
Happy coding!