Creating a Cohesive Color System
There are many ways to express colors in digital design. Hex code, RGB, HSV, CIE-Lab, and simple CSS. In October of 2018 our company’s design team began to take a second look at their current color system. The catalyst for this color exploration came from the KMX Blue family having a very inconsistent change over the set values.
Our first task was to understand where the current system came from. The system had been around since 2014 and heavily relied on Material Colors for several of the color families. Our red, green, yellow, gray, and lightblue families were pulled directly from Google. Our brand blue family was hand-created but the method of creating it was not ideal. When we looked under the hood of KMX Blue we realized a major flaw.
Because we followed Material Design rules we put our main blue, #003366, in the 500 slot which should be the base color. The issue with this approach was that #003366 is naturally a dark color. This led to 700 and 900 values having very little variance while the 100 and 300 have a much larger variance to the point of looking disconnected from the overall family. Luckily by 2018, Google had released a palette generator that can use one hex value to create the whole family. This was our first major find; our brand blue should be in an 800 slot and not 500.
With the palette generator we made the first change to the color system. All of KMX Blue family had their hex codes changed, except for #003366. If we had stopped here it still would have been a great change. Fortunately natural curiosity kicked in and the question became, “How does Google determine what defines the individual values of a color family.” The next several weeks were a deep dive into competitive research. One of our biggest inspirations was Atlassian’s color system. It was cohesive, had guidance around color contrast, but most importantly it was playful.
After seeing the possibilities that a color system can have we dove into exploration with Illustrator. The article gave us a great head start in terms of laying out the HSV grid, the curve used to define the color family values, and the conversion of all colors to grayscale to achieve cohesion. We started by taking the hues of our current system’s 500 values and using those as the basis of our HSV grids. This gave us 3 blue, 1 teal, 1 red, 1 yellow, & 3 green hues to start exploring.
We started in the same way Mineral had, by plotting a start, middle, & end value just to see what we could create. We used the same “draw a curve” approach outlined in the article and were constantly checking individual values against the gray pattern that we created. We used grayscale K-percentages to define our individual values and used Illustrator’s ‘Convert to Grayscale’ on every hue value we found to make sure they matched (Fig.4).
One thing we quickly checked was if our current color system had symmetrical color contrast. Unfortunately, none of the families passed this test. This lack of symmetry led to very few color combinations being available to us. It also bolstered our case for reworking the entire color system.
In order to get the symmetry we wanted we had to pinpoint 500 values that were appealing but also passed color contrast with a white foreground. This led to the arduous process of laying out each dot of the 100 x 100 HSV grid, converting each one to grayscale, then eliminating any dots that didn’t line up with our desired K-percentages. This method gave us our first breakthrough. We realized that a single hue could have multiple values that fall into our K-percentages.
With this initial research, there was enough interest from the lead designers that we were given the go ahead to rework the color system so long as #003366 & #FFD900, our brand logo colors respectively, were still in the system. Their interests were piqued by the symmetrical aspect and basing the system around WCAG color contrast. By the beginning of November, we had a strong understanding of what we wanted from Color System 2.0.
- A color system that is grounded in color contrast compliancy
- A color system that is cohesive within the family and between families
- A color system that can last several years and not look dated
The next few days were spent experimenting with how to easily create these 100 x 100 HSV grids. The dots were a good start but not easily scalable since we’d have to manually change each dot if we wanted to try a different hue value. We abandoned the dots for the time being and created HSV grids by applying a white to black gradient (Vibrance) on-top of a white to hue layer (Saturation) in Photoshop, putting on a Black & White filter, then exported that image into Illustrator. We used several hues and mapped out how each one plays with the K-percentages we established.
This quick experiment made us realize that the Black & White filter from Photoshop and the ‘Convert to Grayscale’ function in Illustrator led to differing outcomes for the same hue color. We decided Illustrator and Photoshop were not the right medium to continue with creating our color system because deciding what true grayscale was, was shown to be unreliable.
One of our engineers saw an opportunity at this point. He developed a Color Grid Tool that can adapt quickly to any changes we wanted and would make creating our 100 x 100 grids much faster. Instead of having to rely on dots being converted by hand or exporting individual grids with Photoshop, he set up an HSV grid that would convert each dot to RGB so it could be consumed appropriately. Next, he added a filter that would calculate whether the individual RGB dots would pass contrast compliancy with a white foreground which solved our problem of pinpointing 500 values that pass compliancy.
This seemingly simple filter gave us our first breakthrough in our color research. First, we learned that some hues naturally have more options for color contrast (i.e. blues, purples, & reds). Second, we learned that the edge of compliancy for every hue had a recurring theme. We took several samples from hue 210 and a few different hues to try to understand why these values were the start to the AA rating. Our breakthrough came from when we realized that every sample point we took had a Lightness value of around 49 but never more than 50 when converted to CIE-Lab.
This completely changed our direction going forward. Converting RGB to grayscale was easy enough but converting RGB to CIE-Lab would be more trustworthy since we’d be dealing with integers rather than hex codes or K-percentages to define our individual values. Our first pass at using the newly coined L*-value pattern was taking the hex codes that matched our K-percentages and converting those to CIE-Lab.
The next feature for the Color Grid Tool came just 3 days after all these findings. Instead of just rendering which values would pass compliancy, we added a Color Ramp filter which only rendered values whose CIE-Lab Lightness value matched our predetermined L*-values. This meant that all of the guesswork around converting values to grayscale to see if they match up was completely removed. We could now input any hue we wanted and a grid with only the needed values would be exported. This increased our efficiency ten-fold.
The next several weeks were spent creating color families using different methods. Our main methods were called “Around the Edge”, “45º Line”, & “Curved”. Each method produced different results but each result produced a cohesive family. We knew we were on the right track but one obstacle we were consistently running into was our yellow family’s values. With our current L*-values, we saw a steep decline in usable colors after the 300 value in any yellow hues.
We tried to solve this problem by making a second set of L*-values specifically for “light” colors (ie. orange & yellow). We shortened the variance between each ramp and cut out the 500, 600, 700, 800, & 900 ramps.
Unfortunately, this exception went against our second rule for the color system, cohesion within and between families. After a few more rounds of trying to find a way to incorporate yellow into the Color System we made the decision to put it aside and use the Material palette generator with #FFD700. Since this tool helped us understand our mistake all the way back with our KMX Blue family, it was fitting to use it on KMX Yellow even if they were small tweaks to the individual values.
By the beginning of December we had a solid MVP for the Color System. During our iterations in late November we were able to slim down the system to 6 color families by abandoning the superfluous blue families.
We went ahead with the “Curved” method for all the colors since that gave us the best spread of vibrancy. A nice opportunity presented itself with our blue and slate families; the hue 210 could be used for both. We achieved this by going counter-clockwise on the hue grid rather than clockwise. This “inverted” color family led to Slate 210 having a subtle blue feel towards the darker values.
Here are some other big decisions we made to get to an MVP.
- The Orange family was removed because it’s use was not prevalent in the current website and instead Yellow-900 would be our orange if needed
2. Raspberry was added in order to provide options for pops of color
3. KMX Blue, Sky Blue, Cyan, & Royal Blue were consolidated into one blue family
After our MVP was established we wanted to call out a few accomplishments. First off we now had a very cohesive color system and had a wide range of light to dark values and didn’t have to sacrifice vibrance. We called out as many 1-to-1s with the old and new system so any designers that questioned “where did my ___ color go?” were addressed.
With a good MVP established we began compiling our case study so that we can go to any exec, stakeholder, or team and explain exactly why we made these changes and how it’ll affect their product. The main things we pointed out were the lack of cohesion in the old system, the increase of color combination opportunities, & the need for a more own-able color system.
Fig. 17: These lines depict the main difference between the two color systems. In the old system (a) the variance lines did not match up which led to a lack of cohesive. The new system (b) uses the same line for all color families to ensure cohesion. The L*-values are evenly divided between less than 50 & greater than 50 to create a symmetrical contrast grid.
After our initial feedback from other designers we had a good idea of some tweaks we wanted to do. First was reducing the jump between 50 and 100 since in theory it’s a “half-step” while the others are a “whole-step”. Second is increasing the 50’s family L*-value from 95 to 98 to get very soft colors to use as large backgrounds. But now that the 50 and 100 were so close it broke the perfect symmetry we had before. To solve this we added a 1000 value which gave us 5 values that are compliant with white and 5 values that are compliant with black. The 1000 values were perfect for shadows in illustrations which was a happy surprise.
The last refinements were as follows:
- Reworking the curve we used on Green’s grid since the lower values looked too neon.
- Having the 500 value use one hue degree less than the base hue, 400 uses 2 degrees less, 300 uses 3 degrees less, 200 uses 4 degrees less, 100 & use 5 degrees less.
The change in hue degrees for the lower families was to eliminate some of our colors feeling periwinkle or becoming too pastel. It also gave us one more own-able aspect of our system. With these two refinements approved by all the stakeholders and execs we had our final new color system.
In order to validate our thoughts on CIE-Lab being the best indicator for color contrast ratio we mapped out a grid of L*-value background and L*-value foreground. Our months of research proved positive when the grid was laid out and a pattern was shown. Several additional “tests” were run by focusing on the L*-value of the color value and the grid was confirmed. This graph is the final product of all of our research.