Light mode/Dark mode: Dynamic theming through SCSS mixin

Initial Attempt: Flow Control

$dark-theme: false !default;
$bg: #ffffff !default;
$text: #000000 !default;
$brand: #456789 !default;
@if $dark-theme {
$bg: #111111;
$text: #eeeeee;
$brand: #abcdef
}
p {
color: $text;
background-color: $bg;
}
button {
background-color: $brand;
color: $text;
}
a {
color: $brand;
}

The Problem

p {
color: #000000;
background-color: #ffffff;
}
button {
background-color: #456789;
color: #000000;
}
a {
color: #456789;
}

New Approach

<div className="dark-theme">
<p>Paragraph</p>
<button>Button</button>
<a href="/">Anchor</a>
</div>
.light-theme p {
color: #000000;
background-color: #ffffff;
}
.light-theme button {
background-color: #456789;
color: #000000;
}
.light-theme a {
color: #456789;
}
.dark-theme p {
color: #eeeeee;
background-color: #111111;
}
.dark-theme button {
background-color: #abcdef;
color: #eeeeee;
}
.dark-theme a {
color: #abcdef;
}

The Solution

$themes: (
light: (
text: #333333,
bg: #ffffff,
brand: #567567,
),
dark: (
text: #ffffff,
bg: #333333,
brand: #abcabc,
),
);
@mixin themify($themes) {
@each $name, $values in $themes {
.#{$name}-theme {
$theme-map: $values !global;
@content;
}
}
}
@function themed($key) {
@return map-get($theme-map, $key);
}
@include themify($themes) {
p {
color: themed("text");
background-color: themed("bg");
}
button {
background-color: themed("brand");
color: themed("text");
}
a {
color: themed("brand");
}
} ;

Last words

/* input.scss */@include themify($themes) {
p {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
border-width: 10px;
border-radius: 10px;
width: 50px;
height: 50px;
transition: smooth;
color: themed('text');
background-color: themed('bg');
}
};
/* output.css */.light-theme p {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
border-width: 10px;
border-radius: 10px;
width: 50px;
height: 50px;
transition: smooth;
color: #000000;
background-color: #ffffff;
}
.dark-theme p {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
border-width: 10px;
border-radius: 10px;
width: 50px;
height: 50px;
transition: smooth;
color: #eeeeee;
background-color: #111111;
}
/* input.scss */p {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
border-width: 10px;
border-radius: 10px;
width: 50px;
height: 50px;
transition: smooth;
}
@include themify($themes) {
p {
color: themed('text');
background-color: themed('bg');
}
};
/* output.css */p {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
border-width: 10px;
border-radius: 10px;
width: 50px;
height: 50px;
transition: smooth;
}
.light-theme p {
color: #000000;
background-color: #ffffff;
}
.dark-theme p {
color: #eeeeee;
background-color: #111111;
}

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store