# 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

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.

## 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

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

## 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>
```

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.

### 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

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