Ogundipe Samuel software engineer and technical writer

A guide to theming in CSS

3 min read 1044

The CSS logo over a yellow background.

Over the years, CSS has evolved to cater to the ever-growing needs and flexibility requirements of modern UI design. The demand for highly customizable applications is rapidly increasing, and with that the need for developers who can create such websites.

Theming is the ability to style various aspects of our website differently depending on a context, while still maintaining visual appeal. It could be as simple as changing colors and backgrounds or font-sizes and icons. In CSS, we can achieve theming by piecing together various CSS variables (props) in a context (e.g, black and white) to enable better presentation of an application.

In this tutorial, we’ll cover how to develop apps that are theme-aware using CSS variables. We’ll also learn how to use CSS variables and JavaScript to customize websites and applications.

CSS Variables

A CSS variable (also called a custom property) is a variable you assign a CSS value to and reuse throughout your application.

In older versions of CSS, it’s common to define different values for CSS properties and apply them repeatedly whereever they are needed. In the example below, the a element is set to black (#000), and although other elements (p) will also need to use the same color value (#000), you need to explicitly type out the color value (#000) every time you want to use it on another element.

a {
  color: #000;
}

p {
  color: #000;
}

With CSS variables, we only need to define the value once and then reference it wherever needed. It is identical to defining a variable in any programming language. In the example below, we declare a variable black at the top level of our CSS document and then reference it wherever it is needed.

:root {
   --black: #000;
}

a {
   color: var(--black);
}

p {
   color: var(--black);
}

N/B: When declaring CSS variables, the syntax is **--**, followed by the name of the variable. To reference it, we call var(--variable-name) on the property we wish to assign it to.

Inheritance

CSS variables can be scoped to certain components in an application and can be overridden in inner components when necessary.

This is one feature that makes CSS variables stand out, and it’s also what makes it perfect for creating theme0aware websites. In the example below, the inner div and outer div have been defined with two different background colors. First, we define --some-color at .outer-div by setting its value to black. Then we redefine it at .inner-div by setting it’s value to white, causing it to override its value under this element.

The first .text-color gets the value that was defined at .outer-div because that is its parent, while the second .text-color div gets it from .inner-div as that is the direct child of that div.

We made a custom demo for .
No really. Click here to check it out.

Switching themes

With the illustrations above, all that’s left to make a theme-able website is to figure out a way to swap the property values of various elements based on the current context.

To better understand the concept, let’s talk about black and white themes. At a very basic level, to support black and white themes on a website, the background and text color will have to alternate to maintain readability. So, when we are viewing the black theme, the text color should be white, and when we are viewing the white theme, the text color should be black.

The following pen shows what the website looks like on a white theme:

The following pen shows what the website looks like on a black theme:

Typically, on a website, we may have a toggle that enables us to switch between the available themes. To change the CSS variables in real-time, we need to add a little bit of JavaScript to control the process.

Let’s create a page with dark and light themes and add some JavaScript so that it switches whenever the checkbox is clicked:

In the CSS above, we define two site-wide color sets:

:root {
    --primary-color: #302AE6;
    --secondary-color: #536390;
    --font-color: #424242;
    --bg-color: #fff;
    --heading-color: #292922;
}

AND 

[data-theme="dark"] {
    --primary-color: #9A97F3;
    --secondary-color: #818cab;
    --font-color: #e1e1ff;
    --bg-color: #161625;
    --heading-color: #818cab;
}

The root contains the default colors needed for the light theme, and “data-theme=dark” contains all the colors needed for a dark theme on various parts of our website.

We’ve also added a toggle box to be used to swap out themes whenever a user clicks.

Next, we add some JavaScript to make the swap possible:

const toggleSwitch = document.querySelector('.theme-switch input[type="checkbox"]');

function switchTheme(e) {
    if (e.target.checked) {
        document.documentElement.setAttribute('data-theme', 'dark');
    }
    else {
        document.documentElement.setAttribute('data-theme', 'light');
    }    
}

toggleSwitch.addEventListener('change', switchTheme, false);

Here’s how we achieved this:

  • We select the checkbox with the query selector
  • We create a function to change the context of the application to dark when checked or light when unchecked
  • Finally, we add an event listener to listen for the actions

A good thing to have on a themeable website is the ability to store the user preference, so the next time the user visits the website it automatically loads up in that context. To achieve that, we will make use of local storage.

Add the following lines to the snippet above:

if (e.target.checked) {
    document.documentElement.setAttribute('data-theme', 'dark');
    localStorage.setItem('theme', 'dark'); //this will be set to dark
  }
else {
    document.documentElement.setAttribute('data-theme', 'light');
    localStorage.setItem('theme', 'light'); //this will be set to light
}

Now that we are saving the user preference, we need to check for it every time a site loads so we know which version to display to the user. Add this snippet at the top level in the Javascript document:

const currentTheme = localStorage.getItem('theme') ? localStorage.getItem('theme') : null;

if (currentTheme) {
    document.documentElement.setAttribute('data-theme', currentTheme);

    if (currentTheme === 'dark') {
        toggleSwitch.checked = true;
    }
}

Here, we check if a theme preference has been stored in local storage. Based on the value stored, we toggle the box (by setting it to true or false) to swap the needed variables.

Conclusion

In this tutorial, we learned about theming and how to create a basic version of a theme-able website using CSS variables. We also learned about variable inheritance and local scoping alongside how to make it all come together using basic JavaScript. To learn more about CSS theming check out the official docs here.

You come here a lot! We hope you enjoy the LogRocket blog. Could you fill out a survey about what you want us to write about?

    Which of these topics are you most interested in?
    ReactVueAngularNew frameworks
    Do you spend a lot of time reproducing errors in your apps?
    YesNo
    Which, if any, do you think would help you reproduce errors more effectively?
    A solution to see exactly what a user did to trigger an errorProactive monitoring which automatically surfaces issuesHaving a support team triage issues more efficiently
    Thanks! Interested to hear how LogRocket can improve your bug fixing processes? Leave your email:

    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/

    LogRocket 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 — .

    Ogundipe Samuel software engineer and technical writer

    2 Replies to “A guide to theming in CSS”

    1. Thanks a lot for this amazing article. Before this article theming concept was just a nightmare for me. But Man u nailed it.

    Leave a Reply