Color Schemes and Theme Switchers (CSS and JS)

A compilation of any information I have for making color schemes and theme switchers (ex. darkmode vs lightmode).

home

Extremely Basic: color-scheme and accent-color

This one is for people who like making minimally styled HTML pages, keeping the default white background and black text. If you like doing this, but would like to make it darkmode instead you can use color-scheme!

html {
  color-scheme: dark;}

Maybe you want to keep everything basic, but want to change the blue color links and form elements use.

html {
  accent-color: purple;}

CSS Variables

Maybe you're the opposite and love using a ton of different colors, but find it difficult to keep track of which color is which, especialy if you're using hex color codes. With variables you can assign color codes a name, and use said name in the CSS instead of a color code. This is particularly helpful when you want to change a color value but you've already used said color code a whole bunch in your CSS. Now all you have to do is change the value of the variable. Variables will also be very useful if you want to make different themes for the same page.

:root {
  --bg: rgb(20,10,10);
  --text: #5A78BC;
  --head: #F4A719;
  --link: hotpink;}

You can name the variables whatever you want, they just need to be in the :root selector and have two dashes (--) infront of the name. The value of them will of course have to be defined as a valid color in whichever format you prefer (rgb, hex, html names, hsl, etc)

The variables will look a little different in the CSS though. You have to put it in var(--variable) form.

body {
  color: var(--text);
  background: var(--bg);}
  
a {
  color: var(--link);}

The background of the page will be dark grey (rgb(20,10,10)), the text of the page will be whatever #5A78BC is, and links will be hot pink!

Switching Themes

This section will be much longer, detailing a variety of ways you can provide different themes or light/dark modes for your readers :3.

Pure CSS: prefers-color-scheme media query

This media query defines CSS styles for viewers who have dark or light mode selected as a preference in their browser settings.

@media (prefers-color-scheme: dark;) {
  body {
    color: white;
    background: black;}}
    
@media (prefers-color-scheme: light;) {
  body {
    color: black;
    background: white;}}

There are two options for prefered color scheme: light and dark. Like with any other media query (@media) you can put specific CSS styling for any elements inside the media query brackets.

You can make one mode "default" by only using a query for the non-default color scheme.

body {
  color: white;
  background: black;}
    
@media (prefers-color-scheme: light;) {
  body {
    color: black;
    background: white;}}

Here I have made darkmode the default style, but if a viewer has lightmode as their prefered browser setting, they will see the styles defined in the media query.

You can of course combine this method with color-scheme or variables.

html {
  color-scheme: light;}
    
@media (prefers-color-scheme: dark;) {
  html {
    color-scheme: dark;}}
:root {
  --bg: navy;
  --text: ivory;}
  
@media (prefers-color-scheme: light;) {
  :root {
    --bg: ivory;
    --text: navy;}}
    
body {
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--text);}

First the default color of the variables are defined (a dark mode in this case), then the variables are redefined for users who prefer light mode, lastly the variables are used to give colors to elements. This makes it so that you only have to redefine the varibles in the media query rather than redefining every property in the CSS that uses color.

The thing about these media queries is that the user can't switch between your color schemes unless they do it in their browser settings, not really convienient. They are also limited to one lightmode and one darkmode, where as you may want to create a bunch of different themes for your viewers to be able to pick from. JavaScript becomes necessary.

JavaScript

We can use JavaScript to either add a stylesheet, or change the value of the :root variables.

Either way we will need at least two buttons and functions (more if you have three or more themes)

<button onclick="darkmode()">dark theme</button>
<button onclick="lightmode()">light theme</button>

Each theme button is given a different function that will be applied when the user clicks the button. These buttons will go in the body where ever you want them to be on your page.

JS with Variables

If you're lazy like me and put your CSS in the style element rather than using style sheets, you can use JS to change the variable values.

<script>
  var rootsel = document.querySelector(':root');
  
  function darkmode() {
    rootsel.style.setProperty('--bg', 'rgb(30,30,30)');
    rootsel.style.setProperty('--text', 'rgb(220,190,170)');}
    
  function lightmode() {
    rootsel.style.setProperty('--bg', 'rgb(250,220,190)');
    rootsel.style.setProperty('--text', 'rgb(35,35,35)');}
</script>

The variable rootsel is defined to select :root, this just makes the following JS a little neater rather than repeating the same chunk over and over. Note that this won't work if you are not using variables in the :root selector.

A function for each theme is named, and in each function every color variable is redefined.

Note that you have to redefine the colors for even your default theme, otherwise viewers will not be able to switch back to it. Unfortunately this means that if you change the default colors in your CSS, you will have to copy the changes in your JS manually.

JS with Stylesheets

Once I figure out a more elegent solution with style sheets I'll add it.

Saving a users Theme

You may want to store a users prefered theme, so whenever they visit your site, they dont have to manually change it every time. This is done using cookies where a small bit of information is stored in the user's browser (not all cookies are inherently invasive like advertisment trackers are).

I have not done this yet, but once I do, I'll document it here.