Kermode

/ˈkɜːrmoʊd/
The Spirit Bear

Written by Gray Gilmore

I make websites for a living. I love CSS and building simple and modular stylesheets. Somewhere along the way I also turned into a Ruby developer. Life comes at you fast I guess. You can read my resume to learn about my journey so far.

You can find me as @graygilmore on several platforms:

Good ol' fashion email works, too: hello@kermode.co

You can subscribe to this blog via RSS: XML, JSON

Getting started with CSS Variables

CSS Variables are on their way to prime time in front-end development. Pre-processor variables are something that most front-end developers are already familiar with but this new feature is a little different.

Note: I’m going to be referring to Sass in this post but the examples would apply to LESS, Stylus, or anything else you might use.

Pre-processor variables

Developers have long felt the need for variables in their stylesheets. This makes sense! We use them in almost all of the other languages that we use. They can reduce duplication, simplify code, and give values a great semantic meaning ($font-size-base as opposed to 16px). This desire was partially solved with the introduction of variables in pre-processors like Sass.

Sass variables are great but they have one big limitation: they have to be set before the styles are even sent to the browser. This is why calling them “variables” has always been a little misleading. Calling them “constants” would probably be more accurate to what these values represent.

CSS variables

Enter the new kid on the block: CSS Variables. Instead of relying on our pre-processors to do this dirty work for us, what if CSS itself had a concept of variables? That’s what the W3C team set out to solve (a process that started quite a few years ago).

Technically, CSS variables are actually considered custom properties. They use a brand-new syntax that might be a little perplexing to those that are used to the Sass counter part.

Variables are defined like this:

--custom-property-name: value;

And are used like this:

property: var(--custom-property-name)

Here is a basic example:

:root {
  --font-family-serif: Times;
}

header {
  font-family: var(--font-family-serif);
}

It’s important to note that the above example is valid CSS. Our custom property doesn’t need to be processed before serving the CSS file to the browser. It’s as valid as explicitly writing Times as the value.

header {
  font-family: Times; /* valid CSS */
  font-family: var(--font-family-serif); /* valid CSS */
  font-family: $font-family-serif; /* invalid CSS */
}

Root pseudo-class

You can declare CSS variables on a pseudo-class defined as :root if your variable is more global in nature and does not belong to a particular class or element.

In our example above we use the :root declaration to store our serif font-family in.

Inheritance

Because custom properties are valid CSS they follow the same inheritance rules of other CSS properties. This means we can overwrite CSS variables by simply redefining the value (just like we would do for, say font sizes).

Expanding on our font family example:

:root {
  --font-family-heading: Times;
}

.fancy-heading {
  --font-family-heading: Helvetica;
}

h1,
h2,
h3 {
  font-family: var(--font-family-heading);
}

Any heading that uses the .fancy-heading class will use Helvetica instead of Times as its font. This is awesome! We don’t need to redefine the font-family declaration on our headings we just need to change the CSS custom property value.

Dynamic properties

Now that we’ve gotten a taste of how we can modify CSS variables with classes we can explore what I’m going to describe as “dynamic CSS variables”. What I mean by this is that I’m not going to modify a custom property via a class name. Instead, I’m going to create custom properties that dynamically react to the browser.

Here’s a simple example of a content wrapper that uses different content padding dependent on the viewport size (Sass):

$site-padding-small: 1rem;
$site-padding-medium: 2rem;
$site-padding-large: 3rem;

.content {
  padding: $side-padding-small;

  @media screen and (min-width: 769px) {
    padding: $site-padding-medium;
  }

  @media screen and (min-width: 1200px) {
    padding: $site-padding-large;
  }
}

Using a custom property allows us to abstract the logic from our class styling to another, more appropriate area:

:root {
  --site-padding: 1rem;
}

@media screen and (min-width: 769px) {
  :root {
    --site-padding: 2rem;
  }
}

@media screen and (min-width: 1200px) {
  :root {
    --site-padding: 3rem;
  }
}

.content {
  padding: --site-padding;
}

Our .content class now only has a single style defined on it. Awesome! This is just a small example on an extremely simple class. The real benefits to this kind of optimization will come from more complex, real-world stylesheets.

Browser support

Okay, unlike CSS Grid Layout the outlook for CSS Variables isn’t as great.

The good news: we get green across the board for:

The bad news: no version of Internet Explorer (including Edge) currently supports this. Microsoft’s Edge team is currently working on it but lacking support for IE 11 may be a deal breaker for a lot of folks.

You may be able to get around the lack of IE/Edge support by utilizing CSS @supports but that might not be an option for some of you.

More Reading