How to change CSS :root color variables in JavaScript

Alright, I'm creating a system for my webpage that allows users to change the theme. How I want to accomplish this is by having all the colors as variables, and the colors are set in the :root part of the CSS.

What I want to do is change those colors via JavaScript. I looked up how to do it, but nothing that I attempted actually worked properly. Here's my current code:

CSS:

:root {
  --main-color: #317EEB;
  --hover-color: #2764BA;
  --body-color: #E0E0E0;
  --box-color: white;
}

JS:

(Code to set the theme, it's ran on the click of a button) - I didn't bother adding the :root change to the other 2 themes since it doesn't work on the Dark theme

function setTheme(theme) {
  if (theme == 'Dark') {
    localStorage.setItem('panelTheme', theme);
    $('#current-theme').text(theme);
    $(':root').css('--main-color', '#000000');
  }
  if (theme == 'Blue') {
    localStorage.setItem('panelTheme',  'Blue');
    $('#current-theme').text('Blue');
    alert("Blue");
  }
  if (theme == 'Green') {
    localStorage.setItem('panelTheme', 'Green');
    $('#current-theme').text('Green');
    alert("Green");
  }
}

(Code that is ran when the html is loaded)

function loadTheme() {
  //Add this to body onload, gets the current theme. If panelTheme is empty, defaults to blue.
  if (localStorage.getItem('panelTheme') == '') {
    setTheme('Blue');
  } else {
    setTheme(localStorage.getItem('panelTheme'));
    $('#current-theme').text(localStorage.getItem('panelTheme'));
  }
}

It shows the alert, but does not actually change anything. Can someone point me in the right direction?


Thank you @pvg for providing the link. I had to stare at it for a little to understand what was going on, but I finally figured it out.

The magical line I was looking for was this:

document.documentElement.style.setProperty('--your-variable', '#YOURCOLOR');

That did exactly what I wanted it to do, thank you very much!


For those who want to modify the actual style sheet the following works:

var sheet = document.styleSheets[0];
sheet.insertRule(":root{--blue:#4444FF}");

More info at here: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule


To use the values of custom properties in JavaScript, it is just like standard properties.

// get variable from inline style
element.style.getPropertyValue("--my-variable");

// get variable from wherever
getComputedStyle(element).getPropertyValue("--my-variable");

// set variable on inline style
element.style.setProperty("--my-variable", 4);

I came here looking how to toggle the :root color-scheme with JavaScript, which sets the browser to dark mode (including the scroll bars) like this:

:root {
    color-scheme: dark;
}

using the @Daedalus answer above, this is how I implemented my dark mode detection from user preference:

    const userPrefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
    const preferredTheme = userPrefersDarkMode ? 'dark' : 'light';
    document.documentElement.style.setProperty("color-scheme", preferredTheme);

or with saved toggle:

    const savedTheme = localStorage.getItem('theme');
    if (savedTheme == 'dark') {
        thisTheme = 'light'
    }
    else {
        thisTheme = 'dark'; // the default when never saved is dark
    }
    document.documentElement.style.setProperty("color-scheme", thisTheme);
    localStorage.setItem('theme', thisTheme);

see also the optional meta tag in the header:

<meta name="color-scheme" content="dark light">