How to use CSS variables like a pro
Tags: css, tutorial, webdev
Published: 2020-03-02 16:13:48

---
title: How to use CSS variables like a pro
published: true
date: 2020-02-27 18:30:39 UTC
tags: css,tutorial,webdev
canonical_url: https://blog.logrocket.com/how-to-use-css-variables-like-a-pro/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/4edwn9rbvtb9jkq3y1r6.png
---
**Written by [Idorenyin Obong](https://blog.logrocket.com/author/idorenyinobong/)**✏️

Like most programming languages, native CSS now has support for variables, and they’re here to stay.

If you know a bit of CSS, chances are you’ve heard of CSS preprocessors such as [Sass](https://dev.to/bnevilleoneill/the-definitive-guide-to-scss-1ign) and Less. You’ve probably used them in your projects regardless of your frontend framework of choice. Or maybe you haven’t and you’ve just used [plain old CSS](https://dev.to/bnevilleoneill/how-to-create-a-yin-yang-symbol-with-pure-css-103m).

Either way, the major selling point of those preprocessors was that you could use variables just like you would in a programming language. You declare a variable, assign it a value, and use it across the document to make maintainability a breeze.

In this tutorial, we’ll provide a soft introduction to this concept by first demystifying CSS variables and then building two simple projects that utilize it. If you’re eager to get in on the action as soon as possible, you can find the code to both projects on CodePen ([here](https://codepen.io/KingIdee/pen/MWwbVBL) and [here](https://codepen.io/KingIdee/pen/JjdbvPX)).

Some [basic CSS knowledge](https://dev.to/bnevilleoneill/the-future-of-css-features-in-2020-91h) is required to follow along with this tutorial. Without further ado, let’s dive in!

## What we will build

To solidify our knowledge about CSS variables, we’ll build two very simple projects. The first will demonstrate how to create button variations. This concept is popular in Bootstrap, where certain elements share CSS rules that give them a default design but are differentiated by colors or other properties. The second project will be a theme-based design — specifically, a light-and-dark theme manipulated by JavaScript.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## How to use CSS variables

Also referred to as custom properties or cascading variables, [CSS variables](https://blog.logrocket.com/how-to-create-better-themes-with-css-variables-5a3744105c74/) have myraid use cases. One of the most common is managing websites in which numerous values are similar to those in the document. This helps to reduce the friction associated with refactoring or updating your code.

### The basics

To declare a variable in CSS, come up with a name for the variable, then append two hyphens (–) as the prefix.

```jsx
element {
  --bg-color: #405580;
}
```

The `element` here refers to any valid HTML element that has access to this CSS file.

The variable name is `bg-color`, and two hyphens are appended. To access a variable, use the `var()` notation and pass in the variable name.

```jsx
body {
  background-color: var(--bg-color);
}
```

The `background-color` will take the value of `bg-color` that we declared earlier. More often than not, developers declare all their variables in the `:root` element of the document.

```jsx
:root {
  --primary-color: #0076c6;
  --blur: 10px;
}
```

Declaring your variables here renders them globally scoped and available to the whole file.

### CSS variables inheritance

Just like traditional CSS, CSS variables are cascading in nature — i.e., they inherit. The value of an element is inherited from its parent if no custom property is defined.

HTML:

```jsx
<div class="container">
  <span class="container-inner"></span>
  <article class="post">
    <h1 class="post-title">Heading text</h1>
    <p class="post-content">Paragraph text</p>
  </article>
</div>
```

CSS:

```jsx
.container {
  --padding: 1rem;
}
.container-inner {
  padding: var(--padding);
}
.post {
  --padding: 1.5rem;
}
.post-content {
  padding: var(--padding);
}
```

The padding of the `.container-inner` and `.post-content` classes will be different because, by default, the target selector will inherit from its nearest parent. In this case, the `.post-content` selector inherits padding value from its direct parent, `.post`, with the value of `1.5rem` rather than `1rem`.

### Fallback and invalid values

When using custom properties, you might reference a custom property that isn’t defined in the document. You can specify a fallback value to be used in place of that value. The syntax for providing a fallback value is still the `var()` notation. Add a list of comma-separated values after the first value. Anything after the first comma is treated as a fallback value.

```jsx
:root {
  --light-gray: #ccc;
}

p {
  color: var(--light-grey, #f0f0f0, #f9f9f9) /* No --light-grey, so #f0f0f0 is 
  used as a fallback value */
}
```

Did you notice that I misspelled the value `--light-gray`? This should cause the value to be undefined, in which case the browser would use the first fallback value. If, for some reason, it can’t find the fallback value, the next value would kick in, and so on. The browser will use the initial default color if it can’t find any of the provided values.

Another use case for fallback values is when a value isn’t valid to a property that is provided.

```jsx
:root { 
  --text-danger: 16px; 
} 

body { 
  color: var(--text-color); 
} 
```

In this snippet, the `--text-danger` custom property was defined with a value of `16px`, which isn’t technically wrong. But when the browser substitutes the value of `--text-color` in place of `var(--text-color)`, it tries to use a value of `16px`, which is not a valid property value for color in CSS.

The browser treats it as an invalid value and checks whether the color property is inheritable by a parent element. If it is, it uses it. Otherwise, it falls back to a default color (black in most browsers).

Now let’s dig into our first project.

## Project 1: Building a button variation

In CSS frameworks such as Bootstrap, variables make sharing a base design across elements much easier. Take the `.bg-danger` class, which turns an element’s background color to red and its own color to white. In this first project, you’ll build something similar.

Start by creating a project folder. In your terminal, you can run these commands one after the other.

```jsx
# create a base project folder
mkdir css-variables-pro 

# change directory to the created folder 
cd css-variables-pro

# create a new folder for the first project
mkdir button-variations

# change directory to the new folder
cd button-variations

# create two files
touch variations.html variations.css
```

This will create a project folder called `css-variables-pro`. This folder will house the two projects you’ll build. Next, created a subfolder called `button-variations` and two files for the first project.

Paste the following snippet in the `variations.html` file you created.

```jsx
<!-- css-variables-pro/button-variations/variations.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>CSS Variables - Button Variations</title>
    <link rel="stylesheet" href="variations.css" />
  </head>
  <body>
    <section>
      <div class="container">
        <h1 class="title">CSS Color Variations</h1>
        <div class="btn-group">
          <button class="btn primary">Primary</button>
          <button class="btn secondary">Secondary</button>
          <button class="btn link">Link</button>
          <button class="btn success">Success</button>
          <button class="btn error">Error</button>
        </div>
      </div>
    </section>
  </body>
</html>
```

The structure of this markup is pretty standard. Notice how each button element has two classes: the `btn` class and a second class. We’ll refer to the `btn` class, in this case, as the base class and the second class as the modifier class.

Paste this snippet in your `variations.css` file:

```jsx
/* css-variables-pro/button-variations/variations.css */

* {
 border: 0;
}
:root {
 --primary: #0076c6;
 --secondary: #333333;
 --error: #ce0606;
 --success: #009070;
 --white: #ffffff;
}
/* base style for all buttons */
.btn {
 padding: 1rem 1.5rem;
 background: transparent;
 font-weight: 700;
 border-radius: 0.5rem;
 cursor: pointer;
 outline: none;
}
/* variations */
.primary {
 background: var(--primary);
 color: var(--white);
}
.secondary {
 background: var(--secondary);
 color: var(--white);
}
.success {
 background: var(--success);
 color: var(--white);
}
.error {
 background: var(--error);
 color: var(--white);
}
.link {
 color: var(--primary);
}
```

The `btn` class contains the base styles for all the buttons and the variations come in where the individual modifier classes get access to their colors, which are defined at the `:root` level of the document. This is extremely helpful not just for buttons, but for other elements in your HTML that can inherit the custom properties.

For example, if tomorrow you decide the value for the `--error` custom property is too dull for a red color, you can easily switch it up to `#f00000`, and voila: all elements using this custom property are updated with a single change. I don’t know about you, but that sounds like a stress-reliever to me.

Here’s what your first project should look like:

![Screenshot of Completed Button Variation Project](https://i1.wp.com/blog.logrocket.com/wp-content/uploads/2020/02/second-project-screenshot.png?resize=730%2C406&ssl=1)

## Project 2: Building a sitewide theme

In the second project, we’ll build a light-and-dark theme. The light theme will take effect by default unless the user already has their system set to a dark theme. On the page, we’ll create a toggle button that allows the user to switch between themes.

Open the `css-variables-pro` folder you created earlier. Inside the folder, create another folder for your second project and name it `theming`. Or, you can use this command:

```jsx
# create a new folder called theming
mkdir theming
```

Next, move into the theming folder.

```jsx
cd theming
```

Create three new files.

```jsx
# create three files namely theme.html, theme.css, and theme.js
touch theme.html theme.css theme.js
```

This part involves a bit of JavaScript_._ First, open your `theme.html` and paste the following markup.

```jsx
<!-- theme.html -->
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>CSS Variables - Theming</title>
    <link rel="stylesheet" href="theme.css" />
  </head>
  <body>
    <header>
      <div class="container">
        <div class="container-inner">
          <a href="#" class="logo">My Blog</a>
          <div class="toggle-button-container">
            <label class="toggle-button-label" for="checkbox">
              <input type="checkbox" class="toggle-button" id="checkbox" />
              <div class="toggle-rounded"></div>
            </label>
          </div>
        </div>
      </div>
    </header>
    <article>
      <div class="container">
        <h1 class="title">Title of article</h1>
        <div class="info">
          <div class="tags">
            <span>#html</span>
            <span>#css</span>
            <span>#js</span>
          </div>
          <span>1st March, 2020</span>
        </div>
        <div class="content">
          <p>
            Lorem ipsum dolor sit amet consectetur adipisicing elit.
            <a href="#">Link to another url</a> Eius, saepe optio! Quas
            repellendus consequuntur fuga at. Consequatur sit deleniti, ullam
            qui facere iure, earum corrupti vitae laboriosam iusto eius magni,
            adipisci culpa recusandae quis tenetur accusantium eum quae harum
            autem inventore architecto perspiciatis maiores? Culpa, officiis
            totam! Rerum alias corporis cupiditate praesentium magni illo, optio
            nobis fugit.
          </p>
          <p>
            Eveniet veniam ipsa similique atque placeat dignissimos
            quos reiciendis. Odit, eveniet provident fugiat voluptatibus esse
            culpa ullam beatae hic maxime suscipit, eum reprehenderit ipsam.
            Illo facilis doloremque ducimus reprehenderit consequuntur
            cupiditate atque harum quaerat autem amet, et rerum sequi eum cumque
            maiores dolores.
          </p>
        </div>
      </div>
    </article>
    <script src="theme.js"></script>
  </body>
</html>
```

This snippet represents a simple blog page with a header, a theme toggle button, a dummy article, and links to both the corresponding CSS and JavaScript files.

Now, open the `theme.css` file and paste the following.

```jsx
:root {
 --primary-color: #0d0b52;
 --secondary-color: #3458b9;
 --font-color: #424242;
 --bg-color: #ffffff;
 --heading-color: #292922;
 --white-color: #ffffff;
}
/* Layout */
* {
 padding: 0;
 border: 0;
 margin: 0;
 box-sizing: border-box;
}
html {
 font-size: 14px;
 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
  Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
}
body {
 background: var(--bg-color);
 color: var(--font-color);
}
.container {
 width: 100%;
 max-width: 768px;
 margin: auto;
 padding: 0 1rem;
}
.container-inner {
 display: flex;
 justify-content: space-between;
 align-items: center;
}

/* Using custom properties */
a {
 text-decoration: none;
 color: var(--primary-color);
}
p {
 font-size: 1.2rem;
 margin: 1rem 0;
 line-height: 1.5;
}
header {
 padding: 1rem 0;
 border-bottom: 0.5px solid var(--primary-color);
}
.logo {
 color: var(--font-color);
 font-size: 2rem;
 font-weight: 800;
}
.toggle-button-container {
 display: flex;
 align-items: center;
}
.toggle-button-container em {
 margin-left: 10px;
 font-size: 1rem;
}
.toggle-button-label {
 display: inline-block;
 height: 34px;
 position: relative;
 width: 60px;
}
.toggle-button-label .toggle-button {
 display: none;
}
.toggle-rounded {
 background-color: #ccc;
 bottom: 0;
 cursor: pointer;
 left: 0;
 position: absolute;
 right: 0;
 top: 0;
 transition: 0.4s;
}
.toggle-rounded:before {
 background-color: #fff;
 bottom: 4px;
 content: '';
 height: 26px;
 left: 4px;
 position: absolute;
 transition: 0.4s;
 width: 26px;
}
input:checked + .toggle-rounded {
 background-color: #9cafeb;
}
input:checked + .toggle-rounded:before {
 transform: translateX(26px);
}
article {
 margin-top: 2rem;
}
.title {
 font-size: 3rem;
 color: var(--font-color);
}
.info {
 display: flex;
 align-items: center;
 margin: 1rem 0;
}
.tags {
 margin-right: 1rem;
}
.tags span {
 background: var(--primary-color);
 color: var(--white-color);
 padding: 0.2rem 0.5rem;
 border-radius: 0.2rem;
} 
```

This snippet can be divided into two main sections: the layout section and the custom properties section. The latter is what you should focus on. As you can see, the variables are applied above in the link, paragraph, heading, and article elements.

The idea behind this approach is that, by default, the website uses a light theme, and when the box is checked, the values for the light theme get inverted to a dark variant.

Since you can’t trigger these sitewide changes via CSS, JavaScript is critical here. In the next section, we’ll hook up the JavaScript code necessary to toggle between the light and dark themes.

Alternatively, you could trigger a change automatically via CSS using the [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media query to detect whether the user requested a light or dark theme. In other words, you can directly update the website to use the dark variants of the light theme.

Add the following snippet to all the CSS code you just wrote.

```jsx
/* theme.css */
@media (prefers-color-scheme: dark) {
 :root {
  --primary-color: #325b97;
  --secondary-color: #9cafeb;
  --font-color: #e1e1ff;
  --bg-color: #000013;
  --heading-color: #818cab;
 }
}
```

We are listening to the user’s device settings and adjusting the theme to dark if they’re already using a dark theme.

Update the `theme.js` file by adding this snippet:

```jsx
// theme.js
const toggleButton = document.querySelector('.toggle-button');
toggleButton.addEventListener('change', toggleTheme, false);

const theme = {
 dark: {
  '--primary-color': '#325b97',
  '--secondary-color': '#9cafeb',
  '--font-color': '#e1e1ff',
  '--bg-color': '#000013',
  '--heading-color': '#818cab'
 },
 light: {
  '--primary-color': '#0d0b52',
  '--secondary-color': '#3458b9',
  '--font-color': '#424242',
  '--bg-color': '#ffffff',
  '--heading-color': '#292922'
 }
};

function toggleTheme(e) {
 if (e.target.checked) {
  useTheme('dark');
  localStorage.setItem('theme', 'dark');
 } else {
  useTheme('light');
  localStorage.setItem('theme', 'light');
 }
}

function useTheme(themeChoice) {
 document.documentElement.style.setProperty(
  '--primary-color',
  theme\[themeChoice\]['--primary-color']
 );
 document.documentElement.style.setProperty(
  '--secondary-color',
  theme\[themeChoice\]['--secondary-color']
 );
 document.documentElement.style.setProperty(
  '--font-color',
  theme\[themeChoice\]['--font-color']
 );
 document.documentElement.style.setProperty(
  '--bg-color',
  theme\[themeChoice\]['--bg-color']
 );
 document.documentElement.style.setProperty(
  '--heading-color',
  theme\[themeChoice\]['--heading-color']
 );
}

const preferredTheme = localStorage.getItem('theme');
if (preferredTheme === 'dark') {
 useTheme('dark');
 toggleButton.checked = true;
} else {
 useTheme('light');
 toggleButton.checked = false;
}
```

Now let’s break down the current state of the website.

A user visits the page. The media query `prefers-color-scheme` determines whether the user is using a light or dark theme. If it’s a dark theme, the website updates to use the dark variants of the custom properties. Let’s say a user isn’t using a dark theme or their OS doesn’t support a dark theme. The browser would default to the light theme, allowing the user to control that behavior by checking or unchecking the box.

Depending on whether the box is checked or unchecked, the `useTheme()` function is called to pass in the theme variant and save the user’s current selection to local storage. You’ll see why it’s saved in a minute.

The `useTheme()` function is where all the magic happens. Based on the theme variant passed, a lookup is performed on the `theme` constant and used to switch between light and dark modes.

The last piece of the puzzle is persisting the current theme, which is achieved by reading the last preferred theme from local storage and setting it automatically when the user revisits the website.

You may be thinking of a million other ways to achieve this. Feel free to go through the code and make as many changes as you see fit.

Here’s what your second project should look like:

![](https://paper-attachments.dropbox.com/s_25608BA466A49B282F69FA057AB0105DCB070A2A78E4D65458CD554C36622655_1582379372697_Screenshot+2020-02-22+at+2.47.39+PM.png)

## Conclusion

By building these simple projects, you can learn how to use CSS variables like a pro. There’s certainly more to them than I explained, so feel free to mess around with the code to explore further.

CSS variables help simplify the way you build websites and complex animations while still allowing you to write reusable and elegant code. To learn more, refer to the documentation on [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/--*).

* * *
## Is your frontend hogging your users' CPU?

As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, [try LogRocket.](https://logrocket.com/signup/) 

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/403rye2ptzx994uhktk1.png)

[LogRocket](https://logrocket.com/signup/) is like a DVR for web apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.

Modernize how you debug web apps — [Start monitoring for free.](https://logrocket.com/signup/)
* * *

The post [How to use CSS variables like a pro](https://blog.logrocket.com/how-to-use-css-variables-like-a-pro/) appeared first on [LogRocket Blog](https://blog.logrocket.com).