I've stumbled on an article called Create A Dark/Light Mode Switch with CSS Variables which explains how to style your site with CSS variables which you can then change for various "themes". Her solution is to use a little Javascript - and let's be honest, there is nothing wrong with that, everything is using Javascript these days, but what if we mix this idea with "the CSS checkbox hack" as explained in Creating useful interactive elements using only CSS, or "The Checkbox Hack"? Then we could have a controllable theme in our website without any Javascript.

Just in case these sites disappear, here is the gist of it:
  1. Define your colors in the root of the document with something like this:
    :root {
    --primary-color: #302AE6;
    --secondary-color: #536390;
    --font-color: #424242;
    --bg-color: #fff;
    --heading-color: #292922;
    }
  2. Define your themes based on attributes, like this:
    [data-theme="dark"] {
    --primary-color: #9A97F3;
    --secondary-color: #818cab;
    --font-color: #e1e1ff;
    --bg-color: #161625;
    --heading-color: #818cab;
    }
  3. Use the colors in your web site like this:
    body {
    background-color: var(--bg-color);
    color: var(--font-color);

    /*other styles*/
    .....
    }
  4. Change theme by setting the attribute data-theme to 'dark' or 'light'
Now, to use the CSS checkbox hack, you need to do the following:
  1. Wrap all your site in an element, a div or something
  2. Add a checkbox input on the same level as the wrapper and styled to be invisible
  3. Add a label with a for attribute having the value the id of the checkbox
  4. Add in the label whatever elements you want to trigger the change (button, fake checkbox, etc)
  5. Change the theme CSS to work not with [data-theme="dark"], but with #hiddenCheckbox:checked ~ #wrapper, which means "the element with id wrapper that is on the same level as the checkbox with id hiddenCheckbox"
This means that whenever you click on the label, you toggle the hidden checkbox, which in turn changes the CSS that gets applied to the entire wrapper element.

And here is a CodePen to prove it:

See the Pen
rbzPmj
by Siderite (@siderite)
on CodePen.

Comments

Be the first to post a comment

Post a comment