How do I edit a CSS variable using JS?

JavascriptJqueryCss

Javascript Problem Overview


I have these CSS variables to control the colors of my project so I can do theming.

html {
    --main-background-image: url(../images/starsBackground.jpg);
    --main-text-color: #4CAF50;
    --main-background-color: rgba(0,0,0,.25);
    --beta-background-color: rgba(0,0,0,.85);
}

However no matter how I try to change the attribute(the two commented lines tried separately), the closest I get is returning not a valid attribute.

function loadTheme() {
    var htmlTag = document.getElementsByTagName("html");
    var yourSelect = document.getElementById( "themeSelect" );
    var selectedTheme = ( yourSelect.options[ yourSelect.selectedIndex ].value );
    // htmlTag[0].setAttribute('--main-text-color', '#FFCF40');
    // $("html").css("--main-text-color","#FFCF40");
}

the error message

Javascript Solutions


Solution 1 - Javascript

Turns out changing CSS variables is possible using the el.style.cssText property, or el.style.setProperty or el.setAttribute methods. In your code snippets el.setAttribute is incorrectly used, which is causing the error you encountered. Here's the correct way:

document.documentElement.style.cssText = "--main-background-color: red";

or

document.documentElement.style.setProperty("--main-background-color", "green");

or

document.documentElement.setAttribute("style", "--main-background-color: green");

Demo

The following demo defines a background color using a CSS variable, then changes it using the JS snippet 2 seconds after loading.

window.onload = function() {
  setTimeout(function() {
    document.documentElement.style.cssText = "--main-background-color: red";
  }, 2000);
};

html {
    --main-background-image: url(../images/starsBackground.jpg);
    --main-text-color: #4CAF50;
    --main-background-color: rgba(0,0,0,.25);
    --beta-background-color: rgba(0,0,0,.85);
}

body {
  background-color: var(--main-background-color);
}

This will only work in browsers supporting CSS variables obviously.

Solution 2 - Javascript

If you are using :root:

:root {
    --somevar: black;
}

It will be documentElement.

document.documentElement.style.setProperty('--somevar', 'green');

Solution 3 - Javascript

The native solution

The standard methods to get/set CSS3 variables are .setProperty() and .getPropertyValue().

If your Variables are Globals (declared in :root), you can use the following, for getting and setting their values.

// setter
document.documentElement.style.setProperty('--myVariable', 'blue');
// getter
document.documentElement.style.getPropertyValue('--myVariable');

However the getter will only return the value of a var, if has been set, using .setProperty(). If has been set through CSS declaration, will return undefined. Check it in this example:

let c = document.documentElement.style.getPropertyValue('--myVariable');
alert('The value of --myVariable is : ' + (c?c:'undefined'));

:root{ --myVariable : red; }
div{ background-color: var(--myVariable); }

  <div>Red background set by --myVariable</div>

To avoid that unexpected behavior you have to make use of the getComputedStyle()method , before calling .getPropertyValue(). The getter will then , look lik this :

getComputedStyle(document.documentElement,null).getPropertyValue('--myVariable');

In my opinion, accessing CSS variables should be more simple, fast, intuitive and natural...


My personal approach

I've implemented CSSGlobalVariables a tiny (<3kb) javascript module wich automatically detects and packs into an Object, all the active CSS global variables in a document, for easier acces & manipulation.

import {CSSGlobalVariables} from './css-global-variables.js';
let cssVar = new CSSGlobalVariables();
// set the CSS global --myColor value to "green"
cssVar.myColor = "green";

Any change applied to the Object properties, is translated automatically to the CSS variables, and viceversa.

Available in : https://github.com/colxi/css-global-variables

Solution 4 - Javascript

You can simply use the standard way of setting arbitrary CSS properties: setProperty

document.body.style.setProperty('--background-color', 'blue');

body {
  --background-color: red;
  background-color: var(--background-color);
}

Solution 5 - Javascript

For anyone who is struggling with it, if your CSS variable is a sentence you need to wrap it in qoutes.

:root {
  --my-css-var: 'Hello Person!';
}

.selector:after {
    content: var(--my-css-var);
}    

This does not work:

let myVar = 'Hi Person! (doesnt work)';
document.getElementsByTagName('html')[0].style.setProperty('--my-css-var', myVar);

But this does:

let myVar = 'Hi Person! (works)';
document.getElementsByTagName('html')[0].style.setProperty('--my-css-var', '"' + myVar + '"');

Solution 6 - Javascript

You could add something like below (without using class variables)

function loadTheme() {
  var htmlTag = document.getElementById("myDiv");
  var yourSelect = document.getElementById("themeSelect");
  var selectedTheme = (yourSelect.options[yourSelect.selectedIndex].value);
  console.log("selected theme: " + selectedTheme);

  // reset class names
  htmlTag.className = '';
  // add selected theme
  htmlTag.className = 'theme' + selectedTheme;
}

.theme1 {
  color: blue;
}
.theme2 {
  color: red;
}

<div id="myDiv">
  test
</div>
<select id="themeSelect" onChange="loadTheme()">
  <option value="1">Theme 1</option>
  <option value="2">Theme 2</option>
</select>

Solution 7 - Javascript

It would probably be easier to define classes in your CSS that contain the various theme styles (.theme1 {...}, .theme2 {...}, etc) and then change the class with JS based on the selected value.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDavid RichardsView Question on Stackoverflow
Solution 1 - JavascriptBrett DeWoodyView Answer on Stackoverflow
Solution 2 - Javascriptphil294View Answer on Stackoverflow
Solution 3 - JavascriptcolxiView Answer on Stackoverflow
Solution 4 - JavascriptOriolView Answer on Stackoverflow
Solution 5 - JavascriptMarkView Answer on Stackoverflow
Solution 6 - JavascriptblurfusView Answer on Stackoverflow
Solution 7 - JavascriptjohnniebensonView Answer on Stackoverflow