paint-brush
Implement Themes/Dark Mode in Your Front-End in 5 Minutesby@bearded-impala
611 reads
611 reads

Implement Themes/Dark Mode in Your Front-End in 5 Minutes

by Siddhesh MoreJuly 23rd, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Themes/Dark Mode is often the most procrastinated feature of implementing dark mode in your app’s front-end. Write a CSS mixin containing classes of DOM elements we want to style as a part of our theme. Write your code to allow the user to change the class of the <body> element. Use the same setTheme method for the onChange event that already sets the body class and stores the user's. The setTheme is set on a drop-down to select from multiple themes.
featured image - Implement Themes/Dark Mode in Your Front-End in 5 Minutes
Siddhesh More HackerNoon profile picture

No matter if you write your own CSS or use frameworks such as Semantic or Bootstrap, implementing dark mode is often the most procrastinated feature

Let’s cut to the chase:

1. Write a CSS mixin containing classes of the DOM elements we want to style as a part of our theme

.theme(@bg-color,@font-color,@menu,@card-bg) {
  background-color: @bg-color;
  color: @font-color;
  .menu {
    background-color: @menu;
    .menu.transition.visible {
      background-color: @menu;
    }
  }
  .text {
    color: @font-color;
  }
  .ui.card {
    background-color: @card-bg;
    .header,
    .meta {
      color: @font-color;
    }
  }
}

2. Including our mixin in the style-sheet meant to be imported in the entry javascript(index.js) or the topmost component(App.js)

@import "./Theme.less";

//generic
@dark-font: #333;
@light-font: rgba(255, 255, 255, 0.9);

//algae
@algae-bg: rgb(191, 211, 206);
@algae-menu: #116466;
@algae-card: rgba(140, 170, 150, 0.7);
body.algae {
  .theme(@algae-bg,@dark-font,@algae-menu,@algae-card);
}

//charcoal
@charcoal-bg: #373737;
@charcoal-menu: #272727;
@charcoal-card: #1b1c1d;
body.charcoal {
  .theme(@charcoal-bg,@light-font,@charcoal-menu,@charcoal-card);
}

//lavender
@lavender-bg: rgb(224, 191, 224);
@lavender-menu: rgb(180, 140, 180);
@lavender-card: rgba(219, 212, 196, 0.699);
body.lavender {
  .theme(@lavender-bg,@dark-font,@lavender-menu,@lavender-card);
}

//paper
@paper-bg: #f4f4f4;
@paper-menu: rgba(110, 110, 110, 1);
@paper-card: #fff;
body.paper {
  .theme(@paper-bg,@dark-font,@paper-menu,@paper-card);
}

3. Write your code to allow the user to change the class of the <body> element. In my case, I have provided a drop-down.

setTheme(themeName) {
  document.getElementById("body").className = themeName;
  localStorage.setItem("theme", themeName);
}
<Dropdown text="Select Theme" item>
 <Dropdown.Menu>
   <Dropdown.Item
     content="Algae"
     onClick={() => this.setTheme("algae")}
   />
   <Dropdown.Item
     content="Charcoal"
     onClick={() => this.setTheme("charcoal")}
   />
   <Dropdown.Item
     content="Lavender"
     onClick={() => this.setTheme("lavender")}
   />
   <Dropdown.Item
     content="Paper"
     onClick={() => this.setTheme("paper")}
   />
 </Dropdown.Menu>
</Dropdown>

Now depending on whether you want a light switch to go dark or a dropdown to select from multiple themes (I’m using a DropDown from Semantic UI), you can have the same setTheme method for the onChange event.

4. Everything should work now unless the user refreshes. The setTheme method already sets the body class and stores user’s selection to localStorage, but we need to read that on a page load or refresh. Place the following script in your app’s entry point, either index.html or index.js, preferably the latter.

window.onload = function () {
  if (localStorage.getItem("theme")) {
    document.getElementById("body").className = localStorage.getItem("theme") || "paper";
  }
};

All done !!

https://github.com/bearded-impala/CSS-Theming

And the GitHub page of that repository,

https://bearded-impala.github.io/CSS-Theming

Thanks for reading.