CSS colour naming conventions

Hi, I am interested to know what naming conventions people are using or recommend for css colour variables.

Colour names

Looking at various sources it seems a popular scheme is to use colour names a bit like this one.

:root {
    --clr-crimson-300: hsl(348, 83%, 36%);
    --clr-crimson-500: hsl(348, 83%, 45%);
    --clr-crimson-700: hsl(348, 83%, 54%);
    --clr-crimson-900: hsl(348, 83%, 63%);

    --clr-brown-300: hsl(10, 5%, 25%);
    ...
}

.some-section {
    background-color: var(--clr-crimson-500);
}

Here Kevin Powell is using a similar setup to font weights, with 500 being the base colour, higher numbers being heavier darker shades and smaller numbers being lighter shades.

This makes sense to me if you are working from a set colour palette or branding.

Drawback

A potential issue I see is if a request is put in to update a colour, say crimson to orange, you will have to update variable names, their values and all occurences throughout the style sheets.

:root {
    /* all need to be changed */
    --clr-orange-300: hsl(31, 80%, 36%);
    --clr-orange-500: hsl(31, 80%, 45%);
    --clr-orange-700: hsl(31, 80%, 54%);
    --clr-orange-900: hsl(31, 80%, 63%);

    --clr-brown-300: hsl(10, 5%, 25%);
    ...
}

.some-section {
    /* changed here too */
    background-color: var(--clr-orange-500);
}

Generic names

I’m thinking along the lines of primary, secondary, accent etc. This seems to make more sense to me.

/* SASS variables */
$clr-primary: hsl(348, 83%, 45%);

:root {
    --clr-primary-300: #{lighten($clr-primary, 10%)};
    --clr-primary-500: #{$clr-primary};
    --clr-primary-700: #{darken($clr-primary, 10%)};
    --clr-primary-900: #{darken($clr-primary, 20%)};
}

.some-section {
    background-color: var(--clr-primary-500);
}

Here I am using SASS variables. If I need or want to change a colour I only need to change the colours in one place e.g. change the value of $clr-primary from crimson to orange. All the shades will be updated accordingly.

/* Only need to change this line */
$clr-primary: hsl(31, 80%, 45%);

/* The rest stays the same */
:root {
    --clr-primary-300: #{lighten($clr-primary, 10%)};
    --clr-primary-500: #{$clr-primary};
    --clr-primary-700: #{darken($clr-primary, 10%)};
    --clr-primary-900: #{darken($clr-primary, 20%)};
}

.some-section {
    background-color: var(--clr-primary-500);
}

Drawback

SASS/SCSS is a bit behind CSS and it’s newer features. Certainly in codepen if you try to use attr() types e.g. attr(data-width type(<percentage>)) you will get a syntax error. I don’t know if there is a work around, but this could be limiting.

Off topic a bit: Vanilla CSS Version of lighten() or darken()?

I did try to replicate this functionality in vanilla CSS. You can mimik it to an extent with the color() function and calc() or with the colour-mix() function mixing with white or black.

As far as I can tell though, SASS lighten and darken work with luminance values. lighten(hsl(31, 80%, 45%), 10%) is equivalent to an addition e.g. hsl(31, 80%, 55%) and matching this through calculation seems to be overly complicated if not impossible.

Conclusion

Yes so people’s thoughts on this topic. Work works and doesn’t work? Recommendations?

1 Like

I cant say i’ve used variables in my CSS as often as i ought to, and when i have, its because i’ve been handed a pack of color values from a branding guide (“blue, yellow, black, other blue”).

I imagine the naming conventions are much like variable naming conventions in other languages though - it doesnt really matter that much as long as its meaningful.

2 Likes

I use variables to switch between themes. Then I prefer to “target naming” the variables. The benefits in my case I think button despite of dark or light mode (opposite colors)

Like

body[data-theme='rebecca'] {
  --bkgr: hsl(270 80% 90%);
  --btn_txt: hsl(0, 0%, 96.1%);
  --btn: hsl(270 80% 40%);
}
button{
  background-color: var(--btn);
  color: var(--btn_txt)
}
2 Likes

Yes I have done similar in the past with class names, good idea.

We also have the built in system light and dark modes, something I guess to consider in the equation. I need to do a bit more research.

You are right. Much like functions you also have local variables as well, which is a bit of a new one to me. An example I was experimenting with recently.

/* scroller variables */
.scroll-container .text-scroller {
    ....
    
    /* breakpoint sizes in rems */
    --max-font-size: attr(data-font-size type(<number>), 20);
    --min-font-size: attr(data-min-font-size type(<number>), var(--max-font-size));
    --min-width: 30; /* 480px */
    --max-width: 62; /* 992px */
    
    /* clamp calculations */
    --slope: calc((var(--max-font-size) - var(--min-font-size)) / (var(--max-width) - var(--min-width)));
    --yAxisIntersection: calc(var(--min-width) * -1 * var(--slope) + var(--min-font-size));
    --clamped-font-size: clamp(
        var(--min-font-size) * 1rem, 
        var(--yAxisIntersection) * 1rem + var(--slope) * 100 * 1vw, 
        var(--max-font-size) * 1rem
    ) 
}

these variables will then be available to the children elements.

The issue for me is getting that convention right in the first place. Getting it right will make naming elements throughout the project easier and more consistent.

1 Like

Yes, I see that as a major drawback also and from experience with dealing with multiple clients over the years I’ve lost count of the number of times they have changed the color scheme at the final stage or afterwards.

I would abstract the names as you mention to primary, secondary (or whatever suits you) as long as you are consistent and know to what they refer.

I know some people love the utility class/naming approach but it still makes me feel sick :slight_smile: (although I can see the usefulness of perhaps a few standard utility classes)

You could mix the variables a little and do something like:

--color-primary: var(--color-blue-500);

It means you’d only have to make 2 little changes if things change

I prefer to keep it simple and something I can read without referring up and down to see what its supposed to be.

2 Likes

Thanks Paul, I was looking forward to your post :biggrin:

I’m glad you agree about about the naming abstraction, that’s reassuring.

This is why I quite like local variables.

One other thing I am going to be looking into is layers. It’s not something I have used before. Have you? Or is it something you steer clear of.

1 Like

No, I’ve not needed it but I can see it could be useful for large sites, teamwork or frameworks. I also see it as doubling the complexity in working out where the style is coming from by simply looking at the stylesheet.

I think its there to solve specific problems but I can see it being abused and lots of !importants springing up because no one can work out where the style is coming from (which was the problem it was trying to solve I believe).

Maybe I have to see some good use cases but the first example on the mdn site makes little sense :slight_smile:

1 Like

I use custom properties for colors, quite a bit, with names based on the parts of the site that are targeted. Here’s a sample of my CSS:

--font-color:#222;					/* Default font color */
--body-background-color:#444;		/* Background behind page */
--body-border:#AAA;					/* Borders around divs and other box elements */
--content-background-color:#FFFFFF;	/* Color of the main body of the page */
--content-background-offset:#EEE;	/* Color of content areas that are to stand out from regular body content */
--button-color:#DDD;				/* Color for all tab and button links */
--button-background-shiny1:#CCC;	/* Gradient 1 for the background of "shiny" buttons */
--button-background-shiny2:#F0F8F8;	/* Gradient 2 for the background of "shiny" buttons */
--background-shiny:linear-gradient(45deg,
							var(--button-background-shiny1) 0% ,
							var(--button-background-shiny2) 70%,
							var(--button-background-shiny1) 100%);
--nav-color-adjust:sepia(100%) hue-rotate(180deg) saturate(600%) brightness(130%);	/* Adjust icon colors to med blue */

I have a complementary version of the above, for the “dark” color scheme.

–nav-color-adjust is used to modify all navigation icons to be a similar color, so that I don’t need to tweak random icons to match my color scheme:

#n_logo img				{filter:var(--nav-color-adjust)}

I’ve found all this quite handy, once set up, and can run the site through the various usability tools, have them complain about not enough separation between certain colors, and then make one tweak to the CSS to adjust them.

2 Likes

Just looking into it and first thought is nightmare. lol

Example

HTML

<div id='first-container' class="container">
    <p class='first-para'>Lorem ipsum dolor sit amet.</p>
    <p>Quod quia accusamus consequatur vel!</p>
    <p>Libero natus est sed ipsa.</p>
</div>

Standard CSS
The more specific selector wins, the first paragraph will be red and the rest green.

/* higher specificity wins */
#first-container > p.first-para {
    color: red;
}

p {
    color: green;
}

CSS with layers
Second layer overrides previous layer, so all text is green.

@layer base {
    #first-container > .first-para {
        color: red;
    }
}

@layer somelayer {
    /* Second layer wins, regardless of specificity in previous layer */
    p {
        color: green;
    }
}

As you say there will be a lot more use of important!, even if just for debugging.

1 Like

To my mind the thing about variables is, they are “variable”!
As in their value may not always be the same thing that you initially set.
If it will always by what you initially set, then why is it even a variable in the first place?
If I want something to be crimson, I may say color: crimson; without setting up any varialbes.
But if I’m setting up a site with both light and dark colour schemes, I may well use variables for setting up colours, but what is crimson in one theme, isn’t necessarily crimson in the other, so I would avoid such decriptive names for anything that may deviate away from that description.
It’s not unlike the much older issue of using overly descriptive class names. Really useful, up until everything changes, and since variables were born to change, how do you see this working out long term?

2 Likes