Takit Isy
Takit Isy

Reputation: 10081

Modify CSS variables / custom properties in jQuery

In my application, I've got some parameters that I wanted to put in CSS variables using jQuery. And I wanted to read them too.

I was having trouble to read the values back of the CSS variables and tried many things… before I found a solution in the “Questions that may already have your answer” while I was typing my question.

Anyway, I attached a snippet, because I need to know:
⋅⋅⋅ Why the method 1 isn't working ?
⋅⋅⋅ Is there a way to get the CSS var value using jQuery ?

I feel like it lacks an easy solution to handle CSS vars… Am I wrong ?
Of course I'll use the javascript solution if there isn't any way. But I'd like to be sure about it.
Thanks in advance for any answer.

// This method doesn't work for writing CSS var.
$(":root").css("--color1", "red");
console.log(".css method on “:root”      :", $(":root").css("--color1"));

// This methods works for writing CSS var:
$(":root")[0].style.setProperty("--color2", "lime");
console.log("[0].style method on “:root” :", $(":root")[0].style.getPropertyValue('--color2'));
#p1 {
  background-color: var(--color1);
}

#p2 {
  background-color: var(--color2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>

<body id="bodyID">
  <p id="p1">p with background --color1</p>
  <p id="p2">p with background --color2</p>
</body>

<html>

Upvotes: 8

Views: 8290

Answers (3)

B L Λ C K
B L Λ C K

Reputation: 642

Here is my version with a live demo -

// array with colors

var colConfig = [
  "default-bg",
  "hoverbg",
  "activebg",
  "maintxt",
  "subtxt",
  "listtxt"
];

let col_1 = ["#ffffff", "#f5f5f5", "#0065ff",'rgba(20, 20, 200, 1)', 'rgba(20, 20, 20, 1)', 'rgba(100, 100, 100, 0.5)'];
let col_2 = ["#000000", "#5f5f5f", "#6500ff", "#1f1f1f", "#f1f1f1", "#000088"];

$("#default").click(function () {
  changeTh(col_1);
});

$("#new").click(function () {
  changeTh(col_2);
});

function changeTh(col) {
  for (let tag in colConfig) { 
    $(":root").css("--" + colConfig[tag], col[tag]);
  }
} 

Upvotes: 0

Nisarg Shah
Nisarg Shah

Reputation: 14541

As BoltClock mentions in their answer, jQuery added support for CSS variables starting from version 3.2.0.

But if you can't upgrade to the higher version for some reason, you could still extend jQuery's $.fn.css method to work with the custom properties.

So here's my attempt at implementing a simple extension that checks if the property being modified is a Custom property or not (by checking that it begins with two hyphens). If it does, the custom property is modified using plain JS, else it calls the original implementation of $.fn.css.

(function() {
  var originalFnCss = $.fn.css;
  $.fn.css = function(prop, val) {

    // Check if the property being set is a CSS Variable.
    if (prop.indexOf("--") === 0) {
      if(val) {

        // Set the value if it is provided.
        for(var idx = 0; idx < this.length; idx++) {
          this[idx].style.setProperty(prop, val);
        }
      } else {

        // Get the computed value of the property.
        return window.getComputedStyle(this[0]).getPropertyValue(prop);
      }
    } else {
      return originalFnCss.apply(this, arguments);
    }
  };
}()); 

Note: At the moment I have tested this extension with jQuery 1.11.1, 2.2.4 and 3.1.1, but do let me know if you find any bugs, or if you have any suggestions.


Now you just need to add the extension just after importing jQuery, or at any point before $.fn.css is invoked. Here's the working snippet:

(function() {
  var originalFnCss = $.fn.css;
  $.fn.css = function(prop, val) {

    // Check if the property being set is a CSS Variable.
    if (prop.indexOf("--") === 0) {
      if(val) {

        // Set the value if it is provided.
        for(var idx = 0; idx < this.length; idx++) {
          this[idx].style.setProperty(prop, val);
        }
      } else {

        // Get the computed value of the property.
        return window.getComputedStyle(this[0]).getPropertyValue(prop);
      }
    } else {
      return originalFnCss.apply(this, arguments);
    }
  };
}()); 

// This method doesn't work for writing CSS var.
$(":root").css("--color1", "red");
console.log(".css method on “:root”      :", $(":root").css("--color1"));

// This methods works for writing CSS var:
$(":root")[0].style.setProperty("--color2", "lime");
console.log("[0].style method on “:root” :", $(":root")[0].style.getPropertyValue('--color2'));
#p1 {
  background-color: var(--color1);
}

#p2 {
  background-color: var(--color2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>

<body id="bodyID">
  <p id="p1">p with background --color1</p>
  <p id="p2">p with background --color2</p>
</body>

<html>

Upvotes: 3

BoltClock
BoltClock

Reputation: 723548

jQuery only supports CSS custom properties in version 3.2.0 and later. There is no support for them in 2.x or earlier, so accessing them with .css() will not work in those versions. If upgrading jQuery is not an option, you will need to use the built-in style object to access them.

$(":root").css("--color1", "red");
console.log(".css method on “:root”      :", $(":root").css("--color1"));

$(":root")[0].style.setProperty("--color2", "lime");
console.log("[0].style method on “:root” :", $(":root")[0].style.getPropertyValue('--color2'));
#p1 {
  background-color: var(--color1);
}

#p2 {
  background-color: var(--color2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<p id="p1">p with background --color1</p>
<p id="p2">p with background --color2</p>

Upvotes: 14

Related Questions