0

I know that this question seems to be asked 1 million time but here there is a little subtility.

Imagine I have some CSS Custom Property like this:

/* Yes the colors are terrible in this exemple, I know */
:root {
    --color_1: salmon;
    --color_2: green;
}
.foo {
    background-color: var(--color_1, var(--color_2, black));
    color: var(--color_2, var(--color_1, white));
}
.foo.inverted {
    background-color: var(--color_2, var(--color_1, white));
    color: var(--color_1, var(--color_2, black));
}

And now in JS I want to get the value of the property "color" of ".foo". With something like this it's pretty easy:

const firstFoo = document.querySelector('.foo');
const gs = getComputedStyle(firstFoo);
const firstFooColor = gs.getPropertyValue('color');

So with thing like this if I do a console.log(firstFooColor), if the first element is just a .foo I will get rgb(0, 128, 0), and if the second element have the class .inverted the color will be rgb(250, 128, 114).

My question is: is there a way to get var(--color_2, var(--color_1, white)) instead of the color output just by selectionning an element?

Everything I've tried has failed. And I don't want to use things like document.styleSheets, parse all, found the class and compare with the classes of the element, and return the value. If a more complex selector it will be horrible and if there is some @media or other it will be pratically impossible...

Thanks in advance for your help!

Ken La
  • 161
  • 7
  • 2
    What do you want to use that pre-compilation style rule for? I doubt this is possible without manually parsing the style sheet, but if you explain your end-goal it's possible someone can come up with an alternative approach. – DBS Sep 05 '22 at 11:00
  • What you are asking is not possible even with `document.styleSheets`, unless you have a CSS parser engine implemented in JavaScript. – n-- Sep 05 '22 at 12:35
  • @DBS Currently I have a complex CSS system for color/theming inspired by this post by Lea Verou (https://lea.verou.me/2020/10/the-var-space-hack-to-toggle-multiple-values-with-one-custom-property/). The problem is that I have nested custom properties and when I try to make some CSS manipulation with JS but want to stock some original value before change, I just get the value and not all the custom property. So I have to change the system of find a solution with JS without parse all stylesheets – Ken La Sep 05 '22 at 13:07

1 Answers1

0

Here's an attempt to achieve this, and it seems to work (with some conditions): https://codepen.io/zvona/pen/yLjyEbX?editors=0111

For instance, I noticed if you define hex values for colors in CSS, then it doesn't recognise them. So feel free to extend this solution with hexToRbg kind of functions.

Also this is also probably the not most performant solution. Plus I noticed later you had requirements to include also secondary variables.

But what the heck, I'll leave the initial solution here for you to get started with and to improve it, whenever needed.

And here's the actual code:

const getUncomputedValue = (elem, target) => {
  const element = document.querySelector(elem);

  if (!element) {
    return;
  }

  const styleValue = getComputedStyle(element).getPropertyValue(target);
  
  if (!styleValue) {
    return;
  }
  
  const allStyling = Array.from(element.computedStyleMap()).filter(([prop, val]) => prop.includes('--') && val[0].toString().includes(styleValue));
  
  return allStyling.map((style) => `var(${style[0]})`).join(',');
};
Samuli Hakoniemi
  • 18,740
  • 1
  • 61
  • 74
  • It's an interesting solution to recreate the var. Just this solution can't help for complex custom property with second parameter and if the computed style is not equal to the value of the defined custom property. (also unfortunately computedStyleMap doesn't work on Firefox). But thank's for your proposal – Ken La Sep 05 '22 at 12:59