Accessing a CSS custom property (aka CSS variable) through JavaScript

JavascriptJqueryCssCss Variables

Javascript Problem Overview


How do you get and set CSS custom properties (those accessed with var(…) in the stylesheet) using JavaScript (plain or jQuery)?

Here is my unsuccessful try: clicking on the buttons changes the usual font-weight property, but not the custom --mycolor property:

<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
  <style>
    body { 
      --mycolor: yellow;
      background-color: var(--mycolor);
    }
  </style>
</head>
<body>

  <p>Let's try to make this text bold and the background red.</p>
  <button onclick="plain_js()">Plain JS</button>
  <button onclick="jQuery_()">jQuery</button>

  <script>
  function plain_js() { 
    document.body.style['font-weight'] = 'bold';
    document.body.style['--mycolor'] = 'red';
  };
  function jQuery_() {
    $('body').css('font-weight', 'bold');
    $('body').css('--mycolor', 'red');
  }
  </script>
</body>
</html>

Javascript Solutions


Solution 1 - Javascript

You can use document.body.style.setProperty('--name', value);:

var bodyStyles = window.getComputedStyle(document.body);
var fooBar = bodyStyles.getPropertyValue('--foo-bar'); //get

document.body.style.setProperty('--foo-bar', newValue);//set

More Information here.

Solution 2 - 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 like 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 CSSGlobalVariablesa tiny (<3kb) javascript helper which automatically detects and packs into an Object all the active CSS global variables in a document, for easier access & manipulation.

// get the document CSS global vars
let cssVar = new CSSGlobalVariables();
// set a new value to --myVariable
cssVar.myVariable = 'red';
// get the value of --myVariable
console.log( cssVar.myVariable );

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

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

Solution 3 - Javascript

The following example illustrates how one may change the background using either JavaScript or jQuery, taking advantage of custom CSS properties known also as CSS variables (read more here). Bonus: the code also indicates how one may use a CSS variable to change the font color.

function plain_js() { 
    // need DOM to set --mycolor to a different color 
    d.body.style.setProperty('--mycolor', 'red');
     
    // get the CSS variable ...
    bodyStyles = window.getComputedStyle(document.body);
    fontcolor = bodyStyles.getPropertyValue('--font-color'); //get
 
    // ... reset body element to custom property's new value
    d.body.style.color = fontcolor;
    d.g("para").style["font-weight"] = "bold";
    this.style.display="none";
  };

  function jQuery_() {
    $("body").get(0).style.setProperty('--mycolor','#f3f');
    $("body").css("color",fontcolor);
    $("#para").css("fontWeight","bold");
    $(this).css("display","none");
  }
  
var bodyStyles = null;
var fontcolor = "";
var d = document;

d.g = d.getElementById;
d.g("red").addEventListener("click",plain_js);
d.g("pink").addEventListener("click",jQuery_);

:root {
     --font-color:white;
     --mycolor:yellow;
    }
    body { 
      background-color: var(--mycolor);
      color:#090;
    }
    
    #para {
     font: 90% Arial,Helvetica;
     font-weight:normal;
    }
    
    #red {
      background:red;
    }
    
    #pink {
      background:#f3f;
    }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<p id="para">Let's try to make the background red or pink and change the text to white and bold.</p>
  <button id="red">Red</button>
  <button id="pink">Pink</button>

Note that with jQuery, in order to set the custom property to a differnt value, this response actually holds the answer. It uses the body element's get() method which allows access to the underlying DOM structure and returns the body element, thereby facilitating the code setting the custom property --mycolor to a new 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
QuestionMarcZView Question on Stackoverflow
Solution 1 - JavascriptCMedinaView Answer on Stackoverflow
Solution 2 - JavascriptcolxiView Answer on Stackoverflow
Solution 3 - Javascriptslevy1View Answer on Stackoverflow