How do I edit a CSS variable using JS?
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");
}
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.
If you are using :root
:
:root {
--somevar: black;
}
It will be documentElement.
document.documentElement.style.setProperty('--somevar', 'green');
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
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);
}
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 + '"');