Make Your CSS Variable Names Suck Less

Use CSS variable names that align with their roles, and that are consistent within their roles.

Navigating a lot of CSS is tedious, especially when you’re unfamiliar with a project. Like self-documenting code, your variables should describe their intent, and follow a convention allowing you to easily understand and add more variables without creating clutter.


Your CSS Variables Are Role Playing

In every project there are always the same few roles that variables will play. You’ll often have two or more colours, a range of font sizes, and a number of widths that content should be limited to.

Other variables, particularly in CSS preprocessors, may define whether you are enabling or disabling a feature.

Developing and sticking to conventions makes it easy to use variables, and makes adding new variables straight forward.


CSS Colour Variable Naming

When developing a convention for naming variables, it’s useful to think of variables in terms of how they relate to each other, and also to their roles and conventions in the real world.

Within the colour spectrum we know we have primary, secondary, and tertiary colours. The words primarysecondary, and tertiary are also an ordinal scale. Complementary isn’t going to fit too well into our model here, but that doesn’t mean our options are exhausted if we have more than three colours on a site.

Most brands have a dominant colour for their brand, and then subsidiary colours that complement that colour. The dominant colour is likely the most important colour – the primary colour for the brand. The second most dominant colour would likely be the secondary colour, and so on. A particular colour may even have a range of tints and shades.

Another important colour is the colour that the site’s text is defined as. This is quite often not one of the brand colours., and is usually a neutral colour, forming the base for all content.

Lastly, black and white are also common in sites, and for consistency we need to ensure that they conform to our naming convention, too.

With all of this in mind, we can put together a list of colour variable names that we can easily build on, and reuse across the site:

/* our base color, with one tint, and one shade - body and typogaphry is generally the base colour */
$clr-base:    #666;
$clr-base-lt: #999;
$clr-base-dk: #333;

/* primary brand color - skyblue - with shades and tints via Sass functions */
$clr-primary:     skyblue;
$clr-primary-lt:  lighten($clr-primary, 5%);
$clr-primary-ltr: lighten($clr-primary, 10%);
$clr-primary-dk:  darken($clr-primary, 5%);
$clr-primary-dkr: darken($clr-primary, 10%);

/* secondary brand color - hotpink - with shades and tints via Sass functions */
$clr-secondary:     hotpink;
$clr-secondary-lt:  lighten($clr-secondary, 5%);
$clr-secondary-ltr: lighten($clr-secondary, 10%);
$clr-secondary-dk:  darken($clr-secondary, 5%);
$clr-secondary-dkr: darken($clr-secondary, 10%);

/* neutrals */
$clr-ntrl-min: #fff;
$clr-ntrl-max: #000;

There are a few things going on here:

  1. Our variable names indicate via the $clr prefix that these variables are all related – they are colours.

  2. We have an ordinal scale for brand colours. If we need to add new brand colours, we’d likely use tertiary, quaternary, and so on.

  3. Black and white are both neutrals, and named consistently with our other colours

  4. Tints and hues are named with respect to the main colour they are associated with, plus a suffix to describe their lightness or darkness with respect to that main colour:

    1. lt => light

    2. ltr => lighter

    3. ltst => lightest etc.

    This is another ordinal scale, describing exactly how our colours are related!

There’s nothing stopping you from adding $clr-success$clr-warning, and other utility colours in the same way. It’s often useful to distinguish utility colours from brand colours, too. This ensures that you always know the role a colour variable plays.


Font Size Variable Naming

The idea above is powerful. If we namespace our variables, and use ordinal scales where it makes sense, our variables are going to tell us exactly what is going on wherever they are used!

Let’s apply this idea to font sizes.

By default, the HTML headings are already ordinal. Similar to colours, we should distinguish heading font sizes from general copy. Not always will heading font sizes address all our font size needs, either. The following will give us a good foundation for managing font sizes, both larger, and smaller than headings:

/* base font size - applied at body / html level */
$fs-base: 16px;

/* larger than heading font sizes */
$fs-giga: 80px;
$fs-mega: 70px;
$fs-kilo: 60px;

/* heading font sizes */
$fs-h1: 36px;
$fs-h2: 32px;
$fs-h3: 28px;
$fs-h4: 24px;
$fs-h5: 20px;
$fs-h6: 18px;

/* smaller than heading font sizes */
$fs-milli: 14px;
$fs-micro: 10px;
$fs-nano:  8px;

As with colour variables, our font-size variables have a $fs prefix. We can easily tell what the role of each variable is, and what it’s relation is with regards to other font-size variables.

$fs-base gives us a reference to whatever value we’ll set the base font size of the site to, we have clearly defined our heading font sizes, and for flexibility we add 3 font sizes greater than and smaller than our heading sizes.

We now have a predictable convention for font sizes for our site, and we can use them to maintain consistent measurements across a site:

h1 { font-size: $fs-h1;}
h2 { font-size: $fs-h2;}
h3 { font-size: $fs-h3;}
h4 { font-size: $fs-h4;}
h5 { font-size: $fs-h5;}
h6 { font-size: $fs-h6;}

.title     { font-size: $fs-h1;}
.sub-title { font-size: $fs-h3;}

This is powerful stuff, and when combined with a similar convention for naming CSS classes, creates an environment that makes writing and maintaining CSS much more enjoyable.


Be Consistent, And Be Unambiguous

The idea is to be clear about what a variable represents, and the idea it belongs to, so that it cannot be confused with the intent of other variables. If you need to add a new variable to a particular role, and it doesn’t feel right, then either change your convention for that role, or re-evaluate the role of that variable.

Take a look at the following:

/* general...? What if we want 'specific' variables, then? */
$general-heading-color: #3f444a;
$general-text-color:    darken(#677581, 5%);
$general-transition:    all 0.3s;

/* primary / nav / default - WHAT?! */
$font-family-primary: "Open Sans", sans-serif;
$font-family-nav:     Roboto, sans-serif;
$font-family-default: "Helvetica Neue", Helvetica, Arial, sans-serif;

This is an example taken from a popular framework, used in production by tens of thousands of teams. Imagine working with variables named like this, compiling to over 11 000 lines of CSS.

In the first group we have a $general prefix.

Let’s break this down:

  1. Two of the three variables represent colour, but specifically for headings and text.
    What if we we want a piece of text to use the heading colour? Assign it the heading colour variable?
    That doesn’t feel right.

  2. Why are the colours for typography, specifically?
    What if we want the colours to be used for backgrounds, borders, or outlines?
    This makes reusing variable awkward.
    Our $clr variables resolve all of these concerns.

  3. The third variable has nothing to do with colour whatsoever.
    Using $general allows for this. A $trns prefix would be a vast improvement here.

Let’s investigate the second $font-family variable set.

  1. All three variables describe a family of fonts. That’s a better start than the first set of variables.

  2. Hang on, primarynav, and default?!
    This is not ordinal or consistent.
    Which components are privy to using the primary font? Should I ever expect a secondary font?
    Am I forbade from using the nav font anywhere other than the nav?
    How do I add other font families?

With a few changes we get the following:

$ff-base:      'Helvetica Neue', Helvetica, Arial, sans-serif;
$ff-alt-alpha: 'Open Sans', sans-serif;
$ff-alt-beta:  'Roboto', sans-serif;
$ff-icon:      'My Icon Font';

$ff-base ties in with our use of base for font-sizes and colours. You can expect that $ff-base will be the default font for our application.

‘Primary’ in terms of a font is ambiguous in this context – couldn’t the primary font be the base font? Does a ‘secondary’ font indicate it is less hierarchically important than ‘primary’, but more than ‘tertiary’?

There’s a lot of what ‘feels wrong’ there. We know that if we’re not using the base font, we’re using an alternate font. The Greek alphabet provides us with an ordinal system, but with far less implied hierarchy than ‘primary’ / ‘secondary’ scale.

Lastly, by adding $ff-icon we clearly describe the intention of the icon font variable. An font composed of images is a decent enough justification to provide a descriptive name. In the unlikely situation of multiple icon fonts, you could again leverage the Greek alphabet to order your fonts.

With a few small changes we have created a lot of meaning and intention in our variables, and using those variables in any context will feel natural.


Wrapping Up

I hope I’ve shed some light on strategies to improve your variable names. A solid front-end framework is built on top of an extensible, reusable, and consistent library of variables.

As with any programming, if something doesn’t feel right, and eats away at you, there’s usually room for improvement. This is no different for CSS variables.

Group variables based on their roles, and use an ordinal scale when it makes sense to differentiate variables within a role.

Now go out and spread the word!

Contact Larry

Larry Botha