Angular Theming: How to Create a Dynamic Theme Switcher for Light & Dark Mode

Angular Theming: How to Create a Dynamic Theme Switcher for Light & Dark Mode

In this article, we will be creating a dynamic Angular app with theme-switching capabilities. We will develop an application that allows users to toggle between light and dark modes.

I’ll walk you through the process of configuring theming by utilizing CSS variables to keep our styles clean and maintainable. Additionally, we’ll implement a theme switcher, making it easy for users to switch between themes.

By the end of this article, you’ll have an Angular app that showcases the power and flexibility of theming with an intuitive user interface. So, let’s dive in and start building your Angular theme switcher!

Creating Angular App

Let’s quickly create a new Angular app using Angular CLI. Open your terminal and run the following command:

ng new angular-theme-switcher

The Angular CLI will create a template application inside the angular-theme-switcher folder. You can run it by navigating to the application folder and executing the following command in your terminal:

npm start

The template app should now be live and accessible at http://localhost:4200.

Adding Theming Configuration

To begin with, open the index.html file and add the data-theme="light" attribute to the <body> element. Your updated index.html file should look like this:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title> Angular Theme Switcher </title>
    <base href="/" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="icon" type="image/x-icon" href="favicon.ico" />
  </head>
  <body data-theme="light">
    <app-root></app-root>
  </body>
</html>

The data-theme attribute allows us to manage theming within our application. By modifying its value, we can update the colors of all the elements based on the selected theme.

Next, create a _themes.scss file inside the src folder and update its content as follows:

[data-theme="light"] {
  --header-background-color: #ffffff;
  --header-border-color: #e5e8ea;
  --header-menu-item-color: #231f20;
  --header-theme-switch-background-color: #cccccc;
  --header-theme-switch-before-background-color: #ffffff;
  --header-theme-switch-checked-background-color: #2196f3;

  --main-content-background-color: #ffffff;
  --main-content-text-color: #231f20;
}

[data-theme="dark"] {
  --header-background-color: #2c3c93;
  --header-border-color: #e5e8ea;
  --header-menu-item-color: #ffffff;
  --header-theme-switch-background-color: #cccccc;
  --header-theme-switch-before-background-color: #ffffff;
  --header-theme-switch-checked-background-color: #2196f3;

  --main-content-background-color: #231f20;
  --main-content-text-color: #ffffff;
}

The code above defines two themes, light and dark. The _themes.scss file serves as a centralized location for the styles of the entire application. Notice that we have defined styles for each element by using CSS variables, which can now be used throughout the application.

Finally, import the _themes.scss file into the styles.scss file to apply the themes to the application. Update the content of the styles.scss file as shown below:

// Importing themes
@import "themes";

html,
body {
  height: 100%;
  margin: 0;
}

Adding a Basic Layout

First, let’s update the content of the app.component.html file to add a simple layout:

<div class="container">
  <header>
    <div class="menu-items">
      <a class="menu-item"> Home </a>
      <a class="menu-item"> Articles> </a>
      <a class="menu-item"> Tags </a>
      <a class="menu-item"> About Us </a>
    </div>
    <div class="theme-switcher">
      <label class="swtich">
        <input
          type="checkbox"
          [checked]="isLightTheme"
          (change)="onThemeSwitchChange()"
        />
      </label>
    </div>
  </header>
  <main>
    <h1> Welcome to Code Beyond Limits </h1>
  </main>
</div>

The code above creates a basic layout with a header containing navigation items and a theme switcher that looks like a toggle. We also have a main section below the header for the page’s primary content.

Next, open the app.component.ts file and update its content as follows:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  public isLightTheme = true;

  onThemeSwitchChange() {
    this.isLightTheme = !this.isLightTheme;

    document.body.setAttribute(
      'data-theme',
      this.isLightTheme ? 'light' : 'dark'
    );
  }
}

In the code above, we initialized the isLightTheme variable and added the onThemeSwitchChange() function, which will be triggered every time the theme switcher is toggled.

Finally, let’s update the app.component.scss file to apply styles to the layout:

.container {
  display: flex;
  flex-flow: column;
  height: 100%;

  header {
    padding: 20px 30px;
    background-color: var(--header-background-color);
    border-bottom: 1px solid var(--header-border-color);
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .menu-items {
    display: flex;
    gap: 15px;

    .menu-item {
      display: inline-block;
      font-size: 20px;
      color: var(--header-menu-item-color);
      padding: 0px 15px;
      cursor: pointer;
    }
  }

  main {
    justify-content: center;
    align-items: center;
    display: flex;
    flex: 1 1 auto;
    background-color: var(--main-content-background-color);

    h1 {
      font-size: 70px;
      color: var(--main-content-text-color);
    }
  }

  .theme-switcher {
    .switch {
      position: relative;
      display: inline-block;
      width: 60px;
      height: 34px;
    }

    .slider {
      position: absolute;
      cursor: pointer;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background-color: var(--header-theme-switch-background-color);
      -webkit-transition: 0.4s;
      transition: 0.4s;
      border-radius: 34px;

      &:before {
        position: absolute;
        content: "";
        height: 26px;
        width: 26px;
        left: 4px;
        bottom: 4px;
        background-color: var(--header-theme-switch-before-background-color);
        -webkit-transition: 0.4s;
        transition: 0.4s;
        border-radius: 50%;
      }
    }

    input {
      opacity: 0;
      width: 0;
      height: 0;
    }

    input:checked + .slider {
      background-color: var(--header-theme-switch-checked-background-color);
    }

    input:focus + .slider {
      box-shadow: 0 0 1px var(--header-theme-switch-checked-background-color);
    }

    input:checked + .slider:before {
      -webkit-transform: translateX(26px);
      -ms-transform: translateX(26px);
      transform: translateX(26px);
    }
  }
}

In the code above, we have defined styles for our basic layout. Notice that we used the CSS variables for colors, which were previously defined in our _themes.scss file.

The Final Result

Our application is now complete and ready for use. To launch it, run the npm start command in your terminal, and then navigate to http://localhost:4200 in your Browser. The final result should look like this:

The finished Angular theme switcher toggling between light and dark mode

Conclusion

This tutorial has guided you through the process of creating a dynamic Angular application with theme-switching capabilities. We’ve covered configuring themes, implementing a theme switcher, and leveraging CSS variables for clean and maintainable styles.

As a result, you now have a fully-functional Angular app that demonstrates the power and flexibility of theming. With this foundation, you can further customize and expand your application to suit your specific needs.

This tutorial serves as a strong starting point for your Angular theming journey. Continue exploring and experimenting with different styles and themes to create even more engaging and user-friendly applications.

Resources

If you want to use this setup for your own projects, you can find the source code on my GitHub repository.