How to change all :root variables with one function
I understand you want to first read all the declared variables from the css and store them, so they might be resetted after applying new values?
This code will do this, given that there's just one ':root' declaration in one stylesheet (easily complemented in case 'splitted' declaration in more places needed)
let variableLookup = {
'--r': {
newValue: 'teal'
},
'--b': {
newValue: 'orange'
},
'--g': {
newValue: 'purple'
}
}
var root = document.querySelector(':root');
function setNewColors() {
const cssText = [...document.styleSheets]
.map(styleSheet => [...styleSheet.cssRules]
.filter(CSSStyleRule => CSSStyleRule.selectorText === ':root'))
.flat()[0].cssText
// cssText = ':root { --r: red; --b: blue; --g: green; }'
cssText.match(/{(.*)}/)[1].trim()
.split(';')
.filter(Boolean)
.forEach(declaration => {
const [variable, oldValue] = declaration.split(':').map(str => str.trim())
let entry = variableLookup[variable]
if (entry) entry.oldValue = oldValue
})
console.log('variableLookup >>', variableLookup)
Object.entries(variableLookup).forEach(([variable, {newValue}]) => {
root.style.setProperty(variable, newValue);
})
}
function resetColors() {
Object.entries(variableLookup).forEach(([variable, {oldValue}]) => {
if (oldValue) root.style.setProperty(variable, oldValue)
})
}
:root {
--r: red;
--b: blue;
--g: green;
}
.text1 {
color: var(--r)
}
.text2 {
color: var(--b)
}
.text3 {
color: var(--g)
}
:root {
--c: magenta;
}
<div class="text1">Hello</div>
<div class="text2">Bye</div>
<div class="text3">World</div>
<button onclick="setNewColors()">Change to new colors</button>
<button onclick="resetColors()">Reset old colors</button>
How to change CSS :root color variables in JavaScript
Thank you @pvg for providing the link. I had to stare at it for a little to understand what was going on, but I finally figured it out.
The magical line I was looking for was this:
document.documentElement.style.setProperty('--your-variable', '#YOURCOLOR');
That did exactly what I wanted it to do, thank you very much!
Get an overview of all css variables set on root
Found the answer thanks to a post on SO. It reads the :root
property from the stylesheet and loops through the properties looking for the --
keyword.
I wasn't a fan of all the filter function chaining, so I'll leave my own solution here.
/**
* Get all simpleResponse CSS variables on the root of the chat widget.
*/
function getCustomizableProperties(): string[] {
// Find the css sheet that includes the simpleResponse CSS settings.
const simpleResponseStylesheet = getSimpleResponseStyleSheet();
if (!simpleResponseStylesheet) {
console.debug('No customizable properties found. Skipping custom theme rendering.')
return [];
}
// Once found, collect the CSS settings and put them into an array.
const properties = getSimpleResponseStyleProperties(simpleResponseStylesheet);
return properties;
}
function getSimpleResponseStyleSheet(): CSSStyleSheet | undefined {
const styleSheets = Array.from(document.styleSheets);
const simpleResponseStylesheet = styleSheets.find(styleSheet => {
if (styleSheet.href === null) {
const cssRules = Array.from(styleSheet.cssRules);
return cssRules.find(rule => rule.cssText.includes('--simpleResponse'))
}
return undefined;
});
return simpleResponseStylesheet;
}
function getSimpleResponseStyleProperties(styleSheet: CSSStyleSheet): string[] {
const cssRules = Array.from(styleSheet.cssRules);
// Casting to any to access properties missing from typing.
const rootStyleRule: any = cssRules.find((cssRule) => {
const rule = cssRule as any;
return rule.selectorText === ':root';
})
const rootStyleProperties = Array.from(rootStyleRule.style) as string[];
return rootStyleProperties.filter(prop => prop.includes('--simpleResponse'));
}
This returns an array of CSS variables
0: "--simpleResponse-background-color"
1: "--simpleResponse-text-color"
2: "--simpleResponse-text-font"
3: "--simpleResponse-text-font-weight"
4: "--simpleResponse-text-font-size"
Change CSS root variable with jquery or javascript
You can do this pretty easy with something like:
document.documentElement.style.setProperty('--themeColor', 'red');
Update:
Not sure if the question was just about changing the color as I thought. Now I've also added a getRandomColor()
example. Just to get random stuff can be a big load of work depending if you want to save the last used color by the user or so ...
// array with colorsvar colors = [ "red", "green", "lime", "purple", "blue"];
// get random color from arrayfunction getColor() { return colors[ Math.floor(Math.random() * colors.length) ];}
// Set the color from arraydocument.documentElement.style.setProperty('--themeColor', getColor());
:root { --themeColor: orange;}
a { color: var(--themeColor)} div { width: 100px; height: 100px; background-color: var(--themeColor);}
<a href="#">Hello world</a><div>Test</div>
Access CSS variable from javascript
Just the standard way:
- Get the computed styles with
getComputedStyle
- Use
getPropertyValue
to get the value of the desired property
getComputedStyle(element).getPropertyValue('--color-font-general');
Example:
var style = getComputedStyle(document.body)
console.log( style.getPropertyValue('--bar') ) // #336699
console.log( style.getPropertyValue('--baz') ) // calc(2px*2)
:root { --foo:#336699; --bar:var(--foo); --baz:calc(2px*2); }
List CSS custom properties (CSS Variables)
Update:
- To catch CORS errors, I added
!styleSheet.href &&
to the firstif
-statement.
One possible solution would be to parse the document.styleSheets
, and then split the rules into properties/values
var allCSS = [].slice.call(document.styleSheets)
.reduce(function(prev, styleSheet) {
if (!styleSheet.href && styleSheet.cssRules) {
return prev + [].slice.call(styleSheet.cssRules)
.reduce(function(prev, cssRule) {
if (cssRule.selectorText == ':root') {
var css = cssRule.cssText.split('{');
css = css[1].replace('}','').split(';');
for (var i = 0; i < css.length; i++) {
var prop = css[i].split(':');
if (prop.length == 2 && prop[0].indexOf('--') == 1) {
console.log('Property name: ', prop[0]);
console.log('Property value:', prop[1]);
}
}
}
}, '');
}
}, '');
:root {
--bc: #fff;
--bc-primary: #eee;
--bc-secondary: #ddd;
}
Getting a calc() CSS variable into JavaScript
- Problem was, you are access root values which returns string.
- and
calc()
function cannot calculate multiplication of 100ms * 44 so, I have changed--loaderSpeed:100
removedms
. and also created new valiable calledloaderSecondsMultiplier
. - After that, I have
getPropertyValue
get css variables values and converted them into a number and then just mutiply them and in last store it infinalTimeout
.
//GETTING DOCUMENT STYLES
let docStyle = getComputedStyle(document.documentElement);
// GEETING CSS VARIABLE VALUES
let loaderSpeed = parseInt(docStyle.getPropertyValue('--loaderSpeed'));
let loaderSecondsMultiplier = parseInt(docStyle.getPropertyValue('--loaderSecondsMultiplier'));
// MUTIPLYING AND STORING IT'S VALUE TO finalTimeout
let finalTimeout = loaderSpeed * loaderSecondsMultiplier;
setTimeout(() => {
const box = document.getElementById('loaderWrapper');
box.style.display = 'none';
}, finalTimeout);
:root {
--loaderSpeed: 100;
--loaderSecondsMultiplier: 44;
}
<div id="loaderWrapper">
<h1>hey</h1>
</div>
Updating a root css style through JavaScript
You can do something like,
document.documentElement.style.setProperty('--property', 'color');
You can visit this link for a demo created by wesbos.
Related Topics
Why Doesn't JavaScript Newlines Work Inside HTML
Trying to Set a Span Element Equal to a Variable Value in a Js Rock, Paper, Scissors Game
JavaScript - Smooth Parallax Scrolling with Mouse Wheel
How to Properly Escape Attribute Values in CSS/Js Attribute Selector [Attr=Value]
Style the Nth Letter in a Span Using CSS
Dynamically Resize Columns in CSS Grid Layout with Mouse
Can Bootstrap (4) Be Integrated Along with Angular Material (2)
Spring Not Finding Resource Files (Css, Jsp...)
Bootstrap Dropdown in Collapse Not Showing on First Attempt
How to Animate the Opacity of the Background of a Div
Find Td with Specific Text, and Operate on the Td Right After That One
Trigger Event Using Jquery on CSS Change
CSS Dropdown Menu: Add Delay on Mouse Out
Make Webelement Visible via Selenium with Python with JavaScript
How to Change CSS Content with Js