Flutter app development tutorials by Andrea Bizzotto

HSL Colors Explained: What they are and when to use them in Dart/Flutter

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:

RGB / HSL Color Picker in Sketch
RGB / HSL Color Picker in Sketch

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 hue goes from 0 to 360 across the whole 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.

Setting the saturation to 0 produces grayscale values
Left: saturation = 0, luminosity: 0. Right: saturation = 0, luminosity: 100

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:

Example HSL Color palettes

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.

Red primary color swatch | Flutter.dev
Red primary color swatch. Source: api.flutter.dev

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:

Example HSL Color palettes
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.

I'll show you some examples where HSL comes handy in upcoming tutorials.

Happy coding!

Want more?

Support my work and fast-track your Flutter learning with my in-depth courses.