[Go Make Things] Creating a semantic color palette

On Monday, we looked at how to create an accessible color palette.

Today, we're going to learn how to take that palette and use it to create semantic color variables that we can use throughout our design system. This approach is at the heart of Kelp, my UI library for people who love HTML.

Let's dig in!

What are semantic colors?

In Monday's article, we built out a collection of CSS variables that use the color's name and shade:

:root {    	--color-cyan-base: #73d7ee;  	--color-cyan-05: #001928;  	--color-cyan-10: #00283c;  	--color-cyan-20: #00415e;  	--color-cyan-30: #00587c;  	--color-cyan-40: #006f9a;  	--color-cyan-50: #008fbf;  	--color-cyan-60: #00add7;  	--color-cyan-70: #13c2e0;  	--color-cyan-80: #85d8eb;  	--color-cyan-90: #c8ecf5;  	--color-cyan-95: #e4f6fa;    }

Arguably, these variables are already semantic. They describe the color and its value.

But if you're using a design system, you don't want to have to change a bunch of specific color names through your CSS files every time you work with a new client or your company rebrands.

In an ideal world, you'd have variable names that describe what the color does rather than what it is, and use those instead.

Things like --color-primary-* and --color-success-*.

Creating semantic color groups

For each color type, we probably need a collection of shades for different use cases…

  • Fill colors
  • Border colors
  • Text colors to use on top of our fills

And for these different colors, we might have a few variants…

  • A muted variant
  • A vivid or vibrant variant
  • Accent variants (hover states and such)

The way the lightness/chroma curve is setup in the color palette generator, a difference of 50 or more in shade variables should result in a WCAG AA passing contrast, and a difference of 60 or more should result in a WCAG AAA passing contrast.

Start with grayscales

Let's start by building out our neutral colors: the grayscale tones we'll use by default.

We'll create *-fill, *-border, and *-on variables in *-muted, *-accent, and *-vivid varieties. For each one, we'll try to use a AAA passing shade difference of 60 or more.

The vivid color is quite dark, so we'll use white for our *-on-vivid variable.

:root {    	--color-neutral-fill-muted: var(--color-gray-95);  	--color-neutral-fill-accent: var(--color-gray-90);  	--color-neutral-fill-vivid: var(--color-gray-30);  	--color-neutral-border-muted: var(--color-gray-90);  	--color-neutral-border-accent: var(--color-gray-80);  	--color-neutral-border-vivid: var(--color-gray-40);  	--color-neutral-on-muted: var(--color-gray-10);  	--color-neutral-on-accent: var(--color-gray-10);  	--color-neutral-on-vivid: white;  	--color-neutral-outline: var(--color-gray-20);    }

Repeating the process with other colors

We'll repeat this process for things like --color-primary* and --color-secondary-*, as well as state-based variables like --color-success-* and --color-danger-*

:root {    	--color-primary-fill-muted: var(--color-blue-95);  	--color-primary-fill-accent: var(--color-blue-90);  	--color-primary-fill-vivid: var(--color-blue-50);  	--color-primary-border-muted: var(--color-blue-90);  	--color-primary-border-accent: var(--color-blue-80);  	--color-primary-border-vivid: var(--color-blue-60);  	--color-primary-on-muted: var(--color-blue-30);  	--color-primary-on-accent: var(--color-blue-20);  	--color-primary-on-vivid: white;  	--color-primary-outline: var(--color-blue-50);    }

This is honestly mostly just a copy/paste/replace process.

Applying the colors in your design system

Let's look at something like a .callout component.

<div class="callout">  	I've got important information. Look at me!  </div>

Inside the class, we'll define a handful of generic CSS variables for your colors. Then, we'll use those colors to set our CSS properties.

(The extra step here will make sense in a minute.)

.callout {  	--background-color: var(--color-fill-muted);  	--color: var(--color-on-muted);  	--border-color: var(--color-border-muted);    	background-color: var(--background-color);  	border: 1px solid var(--border-color);  	border-radius: 0.25em;  	color: var(--color);  	padding-block: 0.75em;  	padding-inline: 0.8125em;  }

So far, so good.

Color variants

Let's say you want some variations on your .callout.

In addition to the default grayscale version, you want ones in your primary and secondary colors, as well as ones you can use as success and danger alerts.

Rather than create component-specific variations like you'd find in a system like BEM, we'll create some more generic modifiers that we can reuse across components.

For example, a .primary class would define a handful of non-semantic CSS variables that map to semantic color variables.

.primary {  	--color-fill-vivid: var(--color-primary-fill-vivid);  	--color-fill-accent: var(--color-primary-fill-accent);  	--color-fill-muted: var(--color-primary-fill-muted);  	--color-border-vivid: var(--color-primary-border-vivid);  	--color-border-accent: var(--color-primary-border-accent);  	--color-border-muted: var(--color-primary-border-muted);  	--color-on-vivid: var(--color-primary-on-vivid);  	--color-on-accent: var(--color-primary-on-accent);  	--color-on-muted: var(--color-primary-on-muted);  	--color-outline: var(--color-primary-outline);  }

As long as we use these same variable names in our components, we can slap the .primary class on any component to change any of the values used to our primary color palette instead of the generic neutral one.

<div class="callout primary">  	I'm now a primary callout!  </div>

We can repeat this process on everything: buttons, tags, progress bars, icons, and so on.

<button>A regular button</button>  <button class="primary">A primary button</button>  <button class="danger">A danger button</button>

Style variations

You can use this same approach to change the style of various components without having to write component-based modifiers that do the same thing on every single component.

For example, imagine you want variations of your components that have no background color and just an outline.

You might create a class like this…

.outline {  	--background-color: transparent;  	--border-color: var(--color-outline);  	--color: var(--color-outline);  }

Which you could then add to your components as a standalone class or with a color variant, like this…

<div class="callout outline">  	I'm an outline only callout.  </div>    <div class="callout primary outline">  	I'm an outline callout in the primary color.  </div>

These classes become Legos you can mix-and-match on any component.

Why do this?

Once you have this setup, updating your colors throughout the whole system becomes trivial.

Let's say you're a freelancer, and you pick up a new client. The last one had a blue and red color brand color. This one uses shades of purple.

You can swap out the --color-primary-* variables in just one spot, like this…

:root {    	--color-primary-fill-muted: var(--color-purple-95);  	--color-primary-fill-accent: var(--color-purple-90);  	--color-primary-fill-vivid: var(--color-purple-50);  	--color-primary-border-muted: var(--color-purple-90);  	--color-primary-border-accent: var(--color-purple-80);  	--color-primary-border-vivid: var(--color-purple-60);  	--color-primary-on-muted: var(--color-purple-30);  	--color-primary-on-accent: var(--color-purple-20);  	--color-primary-on-vivid: white;  	--color-primary-outline: var(--color-purple-50);    }

And now the entire design system picks up the new design.

There's no build step required. No Sass files to compile. The whole thing automatically updates everywhere.

I'll be setting up the theme builder we looked at on Monday to automatically do this mapping for you, so you can just copy/paste/go when setting up a new site.

Learn more about Kelp

I'll be releasing alpha code and documentation on Kelp UI this week. Head over to KelpUI.com to learn more, and get notifications when code is ready to play around with.

Tomorrow, I'm going to show you how this setup also makes it really easy to have light and dark modes without having to write a bunch of conditional code throughout your CSS file.

Like this? A Go Make Things membership is the best way to support my work and help me create more free content.

Cheers,
Chris

Want to share this with others or read it later? View it in a browser.

Share :

Facebook Twitter Google+ Lintasme

Related Post:

0 Komentar untuk "[Go Make Things] Creating a semantic color palette"

Back To Top