DEV Community

Cover image for Smart web design. Part II: Customizable color theme in 10 minutes 🦜⏱
Paul Rumkin
Paul Rumkin

Posted on


Smart web design. Part II: Customizable color theme in 10 minutes 🦜⏱

Customizable color palette use css variables for color values to make it easy to change via JS or CSS. But good theme requires colors with shades.


The oldest and the most popular color model on the Web is RGB (Red, Green, Blue). It has pretty simple and short syntax #ff0000 (red). But it's really hard to remember all the combinations of colors and manipulate them without color picker.

But there is one color scheme which is extremely simple in work! It's HSL (Hue, Saturation, Lightness):

  • Hue tells wether the color be blue, red, yellow, green or violet, it refers to color wheel angle.
  • Saturation tells how much hue is there, wether it fade (0%) or bright (100%).
  • Lightness tells wether it dark (0%, black) or light (100%, white).

HSL represents colors in more human way. Red in HSL is hsl(0, 100%, 50%) to turn it into blue we just need to change hue param hsl(200, 100%, 50%).

Theme Colors

Now we need to define theme colors. We will create duotone theme, but you can use as much colors as you need, just don't overdo it. Let's call our colors major and minor. To receive color shades we will change the lightness parameter. Shades will be named with two digit indexes from lightest to darkest, e.g. --major-10 lightest and --major-90 darkest.

:root {
  /* Major color is red */
  --major-5: hsl(0, 100%, 95%);
  --major-10: hsl(0, 100%, 90%);
  --major-30: hsl(0, 100%, 70%);
  --major-50: hsl(0, 100%, 50%);
  --major-70: hsl(0, 100%, 30%);
  --major-90: hsl(0, 100%, 10%);

  /* Minor color is yellow */
  --minor-5: hsl(50, 100%, 95%);
  --minor-10: hsl(50, 100%, 90%);
  --minor-30: hsl(50, 100%, 70%);
  --minor-50: hsl(50, 100%, 50%);
  --minor-70: hsl(50, 100%, 30%);
  --minor-90: hsl(50, 100%, 10%);

  --bg: white; /* background color */
  --fg: black; /* text color */

Live demo:

Advanced theming

You can customize colors using custom css files in combination with media queries. For example printable version could be black and white only.

Basic theme.css file could look like this:

:root {
  --major-10: hsl(0, 100%, 90%);
  /* ... */
  --minor-10: hsl(50, 100%, 90%);
  /* ... */

  --bg: white;
  --fg: black;

Dark theme

Dark theme section in theme.css:

@media (prefers-color-scheme: dark) {
  :root {
    --major-10: hsl(0, 100%, 90%);
    /* ... */
    --minor-10: hsl(50, 100%, 90%);
    /* ... */

    --bg: black;
    --fg: white;

Printable version

Printable theme section in theme.css:

@media print {
  :root {
    --major-10: hsl(0, 0%, 90%);
    /* ... */
    --minor-10: hsl(50, 0%, 90%);
    /* ... */

Theme switching

There is a lot of options how to implement a switcher, but the simplest one is a switcher that changes link or style elements order, moving the target theme related element to the end of children list. This is how it implemented in live preview:

function applyTheme(name) {
  // Find style element with matching id
  const style = document.getElementById(name + 'Theme')

  // Move it to the end of child list
  const parent = style.parentElement

  // Remember user's choise
  localStorage.setItem('theme', name)

// Get switcher
const switcher = document.getElementById('themeSwitcher')

// React on select input value changed
switcher.addEventListener('change', (e) => {

// Select color in select input and apply theme selection
  switcher.value = localStorage.getItem('theme')

⚠️ Accessibility

Please, don't forget to include high contrast themes in your design. It will be very helpful for people with color blindness.


That's all. Now you know how simple it is to create a customizable CSS design for you site. Using favicon-switcher from my previous article "Smart web design. Part I: light/dark mode favicon." you able to make real stunning design.


Cover image by David Clode on

Top comments (2)

blackinitial profile image
Black Initial

Thanks for sharing, that's helpfully for me to implement on my project 😃

An Animated Guide to Node.js Event Loop

Node.js doesn’t stop from running other operations because of Libuv, a C++ library responsible for the event loop and asynchronously handling tasks such as network requests, DNS resolution, file system operations, data encryption, etc.

What happens under the hood when Node.js works on tasks such as database queries? We will explore it by following this piece of code step by step.