Naming things is tough. I find naming Sass color variables to be particularly problematic.
Consider the following:
Many might consider this to be a poorly named variable. What if the value of
$red were to change to
#00ff00? Now our variable
$red is actually green.
One solution, which I first read here, by Sacha Greif, is to use descriptive variable names like
$red in conjunction with functional variable names like
$color-link. As an example:
// Descriptive color variables. These should never change. $red: #ff0000; $green: #00ff00; $blue: #0000ff; // Functional color variables. These may change, // but should only use existing descriptive variables listed above. $color-link: $red; $color-accent: $green;
This solves the problem of misnamed descriptive variables:
$red is never going to be anything other than
#ff0000. But, I think it introduces a new problem of maintainability. Consider the following:
// Heading colors $color-heading-primary: $black; $color-heading-secondary: $gray-dark; $color-heading-tertiaty: $navy; $color-heading-quaternary: $yellow-bright;
I've just defined four colors that will be used for headings. That's fine enough, but it means that now I have to either remember what each of my
$color-heading-* vars actually equals, or refer back to the Sass partial where they're assigned, whenever I want to use them.
I might also add some border colors:
// Border colors $color-border-primary: $gray-dark; $color-border-secondary: $gray; $color-border-tertiary: $gray-light; $color-border-quaternary: $gray-lighter;
I think the assignments in this block are significantly harder to remember. They're all grays, and they're all used for border colors. Even as the person authoring the CSS on this project, I doubt I could always keep those straight. But the situation is worse still for the person who has to jump into this project after all these variables are already set up. S/he might look at a rule like
border: $border-width-secondary solid $color-border-teriary; and have no idea what what that border actually looks like.
Having bumped into this problem on a number of recent projects, I recently started just using plain old descriptive variable names like
$red: #ff0000; again (this too has already been written about). So when I see a rule like
color: $green-dark;, I can at least understand, to some degree, what color is actually represented by the var
$green-dark. If I ever want to change the value of
$green-dark to be a blue color, I'll just set a new variable
$blue-dark, and then search and replace for
$green-dark. I've found this method easier to maintain, because 1) I've rarely ever needed to change the value of a color variable to something entirely different, and 2) the time gained in not having to memorize/refer back to a bunch of functional variable names more than makes up for any time I need to search and replace new var names.
But, there is still a problem. Consider the values I used for borders in a previous example above:
// Grays $gray-dark: #333333; $gray: #575757; $gray-light: #808080; $gray-lighter: #b3b3b3;
These values are still kind of hard to remember, but they make (some) sense. But what if I wanted to add an even lighter gray:
// Grays $gray-dark: #333333; $gray: #575757; $gray-light: #808080; $gray-lighter: #b3b3b3; $gray-lightest: #e8e8e8;
Now I've got three "light-ish" gray color vars. What if I needed to add a gray that was lighter than the second to last, but still darker than the last?
// Grays $gray-dark: #333333; $gray: #575757; $gray-light: #808080; $gray-lighter: #b3b3b3; $gray-lighter-er: #c4c4c4; // Lame. $gray-lightest: #e8e8e8;
Now things are getting out of hand—these color var names are too hard to understand. I might not remember which is which, and someone jumping into the project certainly won't be able to easily start working with these.
I think Sass maps can solve this. Consider:
// Gray colors $color-map-gray: ( 1000: hsl(0, 0%, 20%), // #333333 2000: hsl(0, 0%, 34.1%), // #575757 3000: hsl(0, 0%, 50.2%), // #808080 4000: hsl(0, 0%, 70.2%), // #b3b3b3 5000: hsl(0, 0%, 76.9%), // #c4c4c4 6000: hsl(0, 0%, 91%) // #e8e8e8 );
Above, I have map containing all my grays. I no longer need to worry about naming each a var for each one, as I can just do a
map-get() for the color I want. The colors are ordered from lightest to darkest, so that someone looking at
color: map-get( $color-map-gray, 4000 ); has a sense of both what that color is, and where it falls in the spectrum of grays used on the site.
hsl() makes ordering the colors much easier than using a hex value. I'm also using a lot of space in between numbers, so that I can add new values in between the existing ones without disrupting anything (a similar approach for
z-index is a good idea):
// Gray colors $color-map-gray: ( 1000: hsl(0, 0%, 20%), // #333333 2000: hsl(0, 0%, 34.1%), // #575757 2500: hsl(0, 0%, 41%), // #696969 <-- New value 3000: hsl(0, 0%, 50.2%), // #808080 4000: hsl(0, 0%, 70.2%), // #b3b3b3 5000: hsl(0, 0%, 76.9%), // #c4c4c4 6000: hsl(0, 0%, 91%) // #e8e8e8 );
You get the idea. I've not tried this on a project yet, but I'm going to—we'll see how it goes. Let me know what you think.