---
# System prepended metadata

title: Theming With Tailwind CSS
tags: [Completed]

---

# Theming With Tailwind CSS

## Introduction
As accessibility becomes increasingly important, it has become necessary to have at least an extra theme (mostly dark) on a web page.
In this article, I will show the ways of creating multiple themes in a Tailwind CSS application as well as create switches to toggle them.
**Tailwind CSS** is a popular, utility-first CSS framework that provides pre-designed CSS classes to quickly and easily style your web pages.
Additionally, it provides a set of customization options, allowing developers to easily tweak and adjust the styles to their specific needs.

## Pre-requisite
To follow this tutorial completely, you should have basic knowledge of the following:
- HTML
- CSS and [CSS variables](https://blog.openreplay.com/working-with-css-variables/)
- Javascript
- TailwindCSS
As well as have the following installed on your machine:
- A Code Editor
- Nodejs and npm 
- Git 

## Installation and Overview
Follow the steps below to start a Tailwind CSS boilerplate 
### Project Starter
In your terminal enter the commands
```bash=
git clone https://github.com/Complexlity/tailwind-theming.git
cd tailwind-theming
npm install
npm run watch
``` 
### Folder Overview
On Completion, you should have a similar folder structure

![](https://i.imgur.com/5Wis40S.png)

For this tutorial, we would work with four files
- index.html
- input.css
- tailwind.config.js
- main.js

## Creating Call To Action Component
1. Update `index.html` with the code below

```htmlembedded=
<!-- index.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Tailwind Theming</title>
    <link rel="stylesheet" href="output.css" />
    <script src="main.js" defer></script>
  </head>
  <body class="bg-gray-400">
    <div class="wrapper mt-16 px-8">
      <div class="theme-container mx-auto max-w-[50rem] rounded-xl shadow-md bg-white">
        <div
          class="lg:py-16 lg:px-8 z-20 mx-auto w-full py-12 px-4 text-center sm:px-6"
        >
          <h2 class="theme-header text-3xl font-extrabold text-black sm:text-4xl">
            <span class="block"> Hey There 👋 </span>
            <span class="block text-indigo-500">
              Happy Learning!!
            </span>
          </h2>
          <p class="mx-auto mt-4 max-w-md text-xl text-gray-400">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat
            necessitatibus eos consequuntur?
          </p>
          <div class="lg:mt-0 lg:flex-shrink-0">
            <div class="mt-12 inline-flex rounded-md shadow">
              <button
                type="button"
                class="w-full rounded-lg bg-indigo-600 py-4 px-6 text-center text-base font-semibold text-white shadow-md transition duration-200 ease-in hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-indigo-200"
              >
                Get started
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

```
Open `index.html` in your browser to see the output below.


![](https://i.imgur.com/tkd1f6O.png)

## Theming with Classes
### Creating dark theme using inline class
The easiest mode of using dark theme in tailwind is using `dark` class. 
Update the code in `tailwind.config.js`.
```javascript=
// tailwind.config.js
module.exports = {
  content: ["./*.html"],
  darkMode: "class",
  theme: {
    extend: {},
  },
  plugins: [],
};
```
```darkMode:class``` enables `dark` state to be used in conjunction with tailwind classes to set different properties between the normal mode and dark mode.
Update `index.html` in the following ways:
- Add `dark` class to the `body` (Line 13)
- Add `dark:bg-gray-800` class to `div.theme-container` (Line 15)
- Add `dark:text-white` class to `h2.theme-header` (Line 19)

See the code below for an illustration
```htmlembedded=
....
<body class="dark ....">
....
    <div class="theme-container dark:bg-gray-800 ....">
....
        <h2 class="theme-header dark:text-white .... ">
....
```
NOTE: `....` represents unchanged code
We added the `dark` to the `body` tag to enable this. Removing it would reset back to normal mode

### Create Toggle 
Now in the current state, we have to manually add or remove the `dark` class from the body but this is usually now what we want. We would want a switch to toggle between these modes.
#### Insert switch button

```htmlembedded=
<!-- Replace index.html -->

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Tailwind Theming</title>
    <link rel="stylesheet" href="output.css" />
    <script src="main.js" defer></script>
  </head>
  <body class="bg-gray-400">
    <div class="wrapper mt-16 px-8">
      <div
        class="theme-container mx-auto max-w-[50rem] rounded-xl bg-white shadow-md dark:bg-gray-800"
      >
        <div class="mx-8 pt-4 text-end">
            
            <!-- Checkbox start -->
          <div
            class="relative mr-2 inline-block w-10 select-none align-middle transition duration-200 ease-in"
          >
            <input
              type="checkbox"
          name="theme-toggle"    id="theme-toggle"
              class="peer absolute block h-6 w-6 cursor-pointer appearance-none rounded-full border-4 bg-white checked:right-0 checked:border-green-400"
            />
            <label
              for="theme-toggle"
              class="block h-6 cursor-pointer overflow-hidden rounded-full bg-gray-300 peer-checked:bg-green-400"
            ></label>
          </div>
          <label
            for="toggle"
            class="theme-text text-bold text- font- font-bold tracking-wider text-gray-700 dark:text-white"
            >LIGHT</label
          >
        </div>
          <!-- Checkbox End -->
        
          <div
          class="lg:py-16 lg:px-8 z-20 mx-auto w-full py-12 px-4 text-center sm:px-6"
        >
          <h2
            class="theme-header text-3xl font-extrabold text-black dark:text-white sm:text-4xl"
          >
            <span class="block"> Hey There 👋 </span>
            <span class="block text-indigo-500">
              Happy Learning!!
            </span>
          </h2>
          <p class="mx-auto mt-4 max-w-md text-xl text-gray-400">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quaerat
            necessitatibus eos consequuntur?
          </p>
          <div class="lg:mt-0 lg:flex-shrink-0">
            <div class="mt-12 inline-flex rounded-md shadow">
              <button
                type="button"
                class="w-full rounded-lg bg-indigo-600 py-4 px-6 text-center text-base font-semibold text-white shadow-md transition duration-200 ease-in hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-indigo-200"
              >
                Get started
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

```
The Output

![](https://i.imgur.com/EGLmJfU.png)


We added a checkbox which would enable the toggle. 

#### Implement Theme Toggling
We need to make use of some Javascript to make the switch work as expected.<br/> Update `main.js` with the code below.
```javascript=
// main.js
const body = document.querySelector("body");
const themeToggle = document.querySelector("#theme-toggle");
const themeText = document.querySelector(".theme-text");
let darkTheme = false;

themeToggle.addEventListener("click", () => {
  body.classList.toggle("dark");
  darkTheme = !darkTheme;
  themeText.textContent = darkTheme ? "DARK" : "LIGHT";
});
```
Here, we get the toggle as well as the body element and create the toggle function to change the state. 
We also change the toggle text when clicked

![](https://i.imgur.com/dt9NieE.gif)


## Theming with CSS Variables

Consider a scenario where you need more than just `light` and `dark` themes. Using the tailwind `dark` class would not be able to handle that. With the help of CSS Variables, you would be able to create a custom design system that handles as many themes as you want.
### Project Starter
- Start a new project folder
- Open the folder on your terminal and run the following:
```bash=
git clone https://github.com/Complexlity/tailwind-theming.git
cd tailwind-theming
npm install
npm run watch
```


Having the same folder structure and files as in the previous project, we create a different component to handle multiple themes.
### Creating Call To Action Component
Copy the code below into `index.html`
```htmlembedded=
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Tailwind Theming</title>
    <link rel="stylesheet" href="output.css" />
    <script src="main.js" defer></script>
  </head>
  <body class="bg-gray-500">
    <div>
      <div class="wrapper mt-16 px-8">
        <div
          class="themed-background bg-gray-200 mx-auto max-w-[50rem] rounded-xl  shadow-md"
        >
          <div class="px-4 pt-4">
            <label
              for="themes"
              class="themed-label text-indigo-600 mb-2 block text-center text-sm font-medium "
              >CHOOSE A THEME</label
            >
            <select
              id="themes"
              class="block w-full cursor-pointer rounded-lg border p-2.5 text-sm outline-transparent"
            >
              <option value="" selected>Default (Light)</option>
              <option value="blue">Blue</option>
              <option value="red">Red</option>
              <option value="purple">Purple</option>
            </select>
          </div>
          <div
            class="relative mx-auto max-w-4xl overflow-hidden sm:rounded-2xl"
          >
            <div
              class="relative mx-auto max-w-2xl py-16 px-4 text-center sm:py-20 sm:px-6 lg:px-8"
            >
              <h2
                class="themed-header text-indigo-600 text-3xl font-extrabold sm:text-4xl"
              >
                <span class="block">Consistency matters.</span>
                <span class="block">Practice makes perfect.</span>
              </h2>
              <p class="themed-subheader text-gray-800 mt-4 text-lg leading-6">
                Ac euismod vel sit maecenas id pellentesque eu sed consectetur.
                Malesuada adipiscing sagittis vel nulla nec.
              </p>
              <div
                class="mx-auto mt-10 max-w-sm sm:flex sm:max-w-none sm:justify-center"
              >
                <a
                  href="#"
                  class="themed-button bg-indigo-600 text-gray-200 flex items-center justify-center rounded-md border border-transparent px-4 py-3 text-base font-medium  shadow-sm sm:px-8"
                >
                  Get started
                </a>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>
```
![](https://i.imgur.com/QTomVFr.png)

We have a similar call to action component with a select button which we would use to toggle themes.
### Create CSS Variables for the colors of `themed-*` elements.
Replace `input.css` with the code below
```css=
/* input.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --color-text-base: #4f46e5; /* bg-indigo-600 */
    --color-text-muted: #1f2937; /* bg-gray-800 */
    --color-fill: #e5e7eb;  /* bg-gray-200 */
    --color-text-inverted: #e5e7eb; /* bg-gray-200 */
    --color-button-base: #4f46e5; /*bg-indigo-600 */
  }
}
```

Here, we create variables from the [tailwind colors](https://tailwindcss.com/docs/customizing-colors) using their hex code equivalent. 


### Add Custom Color Configuration
Update `tailwind.config.js` with the code below
```javascript=
module.exports = {
  content: ["./*.html"],
  theme: {
    extend: {
      textColor: {
        skin: {
          base: "var(--color-text-base)",
          muted: "var(--color-text-muted)",
          inverted: "var(--color-text-inverted)",
        },
      },
      backgroundColor: {
        skin: {
          fill: "var(--color-fill)",
          button: "var(--color-button-base)",
        },
      },
    },
  },
  plugins: [],
};
```
Here, we use the CSS variables to make custom tailwind colors. These colors can be accessed in html elements.
For example, `base` color could be accessed by `text-skin-base` and `fill` color can be accessed by `bg-skin-fill`

### Replace hard-coded colors with the created colors
Update the following elements in `index.html`:
- **div.themed-background** (Line 15 ): Replace `bg-gray-200` with  `bg-skin-fill`
- **label.themed-label** (Line 20 ): Replace `text-indigo-600` with `text-skin-base`
- **h2.themed-header** (Line 40 ): Replace `text-indigo-600` with `text-skin-base`
- **p.themed-subheader** (Line 45): Replace `text-gray-800` with `text-skin-muted`
- **a.themed-button** (Line 54): Replace `bg-indigo-600` with `bg-skin-button` and `text-gray-200` with `text-skin-inverted`

**Note**: Depending on the text editor and code formatting, the line number may vary

```htmlmixed=
....
<div class="themed-background bg-skin-fill mx-auto ...."> 
<!-- bg-gray-200 now bg-skin-fill -->
....
<label for="themes" class="themed-label text-skin-base mb-2 ....">CHOOSE A THEME</label>  
<!-- text-indigo-600 now text-skin-base -->
....
<h2 class="themed-header text-skin-base text-3xl .... "> 
<!-- text-indigo-600 now text-skin-base -->
....
<p class="themed-subheader text-skin-muted mt-4 .... ">
<!-- text-gray-800 now text-skin-muted -->
....
<a href="#" class="themed-button bg-skin-button text-skin-inverted flex ....">
<!-- bg-indigo-600 now bg-skin-button , text-gray-200 now text-skin-inverted -->

```
**Note**: `....` represents unchanged code
Now the component should still look the same but without any hardcoded colors on the elements

### Create Multiple Themes
Now you could create as many themes as you need using the CSS variables. We would create three more namely: *Blue*, *Red* and *Purple*.
Replace `input.css` with the code below
```css=
/* input.css */ 
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --color-text-base: #4f46e5;
    --color-text-muted: #1f2937;
    --color-fill: #e5e7eb;
    --color-text-inverted: #e5e7eb;
    --color-button-base: #4f46e5;
  }

  .blue {
    --color-text-base: #fff;
    --color-text-muted: #bfdbfe;
    --color-fill: #1e40af;
    --color-text-inverted: #1d4ed8;
    --color-button-base: #fff;
  }
  .red {
    --color-text-base: #fff;
    --color-text-muted: #fecaca;
    --color-fill: #991b1b;
    --color-text-inverted: #b91c1c;
    --color-button-base: #fff;
  }
  .purple {
    --color-text-base: #fff;
    --color-text-muted: #e9d5ff;
    --color-fill: #6b21a8;
    --color-text-inverted: #7e22ce;
    --color-button-base: #fff;
  }
}
```
Now we created more themes. We used scoping of CSS variables to achieve it. These colors would only apply under the specific class while the `:root` one remains the default

### Implement Theme Toggling
We already created the select to toggle these themes so now we need to use Javascript to make it work as expected.
Insert the code below into `main.js`

```javascript=
// Insert code into main.js
const themedContainer = document.querySelector("body > div");
const selectOptions = document.querySelector("#themes");

selectOptions.addEventListener("input", (e) => {
  themedContainer.className = e.target.value;
});
```
In the code above, we change the class of the parent element depending on the value of the option selected.
Now the code works the same as the image below.


![](https://i.imgur.com/G7EdBI9.gif)


### Live Link
You can see both methods in action [here](https://tailwind-theming.netlify.app/)


## Information For Usage on Frameworks
Front-end frameworks have become increasingly popular so it is important to know how to apply these methods on your preferred framework
### Installing TailwindCSS
Tailwind is compatible with many front-end frameworks including React, Vue, Angular, Svelte, and the likes

![](https://i.imgur.com/FLv43vY.png)

Head over to the [Tailwind documentation](https://tailwindcss.com/docs/installation/framework-guides) and pick your preferred framework

### Applying Theming Idea When Using Frameworks
In your prefered framework, theming works the same way as we have seen in this article.
#### Using Class
1. Update `tailwind.config.js` by adding `darkmode: "class"`
2. Use the `dark` class on html elements (or Jsx components in some frameworks)
3. Creating and implementing a toggle button

#### Using CSS Variables
1. Create CSS variables representing the themed colors
2. Creating custom tailwind colors with the CSS variables (in `tailwind.config.js`)
3. Use these custom color names in HTML elements (or Jsx components in some frameworks)
4. Create a toggle switch to dynamically change the theme class

## Conclusion
In this article, we looked at how to create a dark theme as well as creating multiple themes using Tailwind CSS. 
With the ease of implementation here and for accessibility reasons, you should always create at least a dark theme for your web sites and applications
