78

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>
Mosh Feu
  • 28,354
  • 16
  • 88
  • 135
MarcZ
  • 803
  • 1
  • 5
  • 5
  • Is `var` supported in CSS? – Praveen Kumar Purushothaman Mar 18 '16 at 15:46
  • 4
    @Gothdo Yes there is. https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables It is still experimental however. Also it's purpose is not meant for things that you change at run-time but for maintainability. If you want things you can change look at [attr](https://developer.mozilla.org/en/docs/Web/CSS/attr) – ste2425 Mar 18 '16 at 15:49
  • 1
    TL;DR : `getComputedStyle(document.documentElement).getPropertyValue('--x')` – ashleedawg Nov 13 '20 at 10:33

4 Answers4

90

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
Dan
  • 5,836
  • 22
  • 86
  • 140
CMedina
  • 4,034
  • 3
  • 24
  • 39
44

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

vsync
  • 118,978
  • 58
  • 307
  • 400
colxi
  • 7,640
  • 2
  • 45
  • 43
  • 3
    I like it for when you need to manipulate the variables in JS, but in my case I only needed to fetch the values. So instead of a full helper library, I just needed a single helper function returning `getComputedStyle(document.documentElement,null).getPropertyValue(varStr);` – ICW Jul 16 '19 at 16:30
  • I know this is an older question, but how would you go about changing the actual var(--varName) dynamically in the stylesheet to the value selected? If I wanted to serve the stylesheet to the user, I would want the user to see the actual color name or hex value instead of var(--varName). See https://stackoverflow.com/q/59507329/10964617 for example – Dave.Q Jan 03 '20 at 17:52
  • @Dave.Q I that case you could use Sass or Less, otherwise i don't see how to expose those values directly – colxi Jan 04 '20 at 15:22
  • @connexo exactly. It outputs `undefined` as expected. Read again the comment before the code snippet. – colxi Dec 17 '20 at 18:01
  • I had a look at the prototype but couldn't find anything. Does someone know if it is possible to get an array of ALL defined custom properties within a document via JavaScript? – exside Mar 20 '23 at 00:36
5

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.

slevy1
  • 3,797
  • 2
  • 27
  • 33
1

You can use getComputedStyle function to get css variables,Here is a example.

const colors = document.querySelectorAll(".color");
const result = document.getElementById("result");
colors.forEach((color) => color.addEventListener("click", changeColor));

function changeColor(event) {
  const target = event.target;
  // get color
  const color = getComputedStyle(target).getPropertyValue("--clr");
  document.body.style.backgroundColor = color;

  // active color
  colors.forEach((color) => color.classList.remove("active"));
  target.classList.add("active");
  
  result.textContent = getComputedStyle(target).getPropertyValue("--clr")
  
}

result.textContent = "#1dd1a1";
body{
  background-color: #1dd1a1;
}

.colors{
  position: absolute;
  padding: 2rem;
  display: flex;
  gap: 1rem;
}

.color{
  display: inline-block;
  width: 2rem;
  height: 2rem;
  background-color: var(--clr);
  border-radius: 50%;
  cursor: pointer;
  transition: $time-unit;

  }
  .color.active{
    border: .2rem solid #333;
    transform: scale(1.25);
  }
<h1>Click to change Background</h1>
<section class="colors">
  <span class="color active" style="--clr: #1dd1a1"></span>
  <span class="color" style="--clr: #ff6b6b"></span>
  <span class="color" style="--clr: #2e86de"></span>
  <span class="color" style="--clr: #f368e0"></span>
  <span class="color" style="--clr: #ff9f43"></span>
</section>

Current Color: <span id="result"></span>
Q10Viking
  • 982
  • 8
  • 9