Get All Css Root Variables In Array Using Javascript And Change The Values
Solution 1:
this script will return an array of root variables in all stylesheets, served from the domain. Out of domain stylesheets are not accessible due to CORS policies.
Array.from(document.styleSheets)
.filter(
sheet =>
sheet.href === null || sheet.href.startsWith(window.location.origin)
)
.reduce(
(acc, sheet) =>
(acc = [
...acc,
...Array.from(sheet.cssRules).reduce(
(def, rule) =>
(def =
rule.selectorText === ":root"
? [
...def,
...Array.from(rule.style).filter(name =>
name.startsWith("--")
)
]
: def),
[]
)
]),
[]
);
Note: a root:
rule in a lower order stylesheet will override a parent root
rule.
Solution 2:
I needed a similar solution today. Here's a quick one on codepen.
// could pass in an array of specific stylesheets for optimizationfunctiongetAllCSSVariableNames(styleSheets = document.styleSheets){
var cssVars = [];
// loop each stylesheetfor(var i = 0; i < styleSheets.length; i++){
// loop stylesheet's cssRulestry{ // try/catch used because 'hasOwnProperty' doesn't workfor( var j = 0; j < styleSheets[i].cssRules.length; j++){
try{
// loop stylesheet's cssRules' style (property names)for(var k = 0; k < styleSheets[i].cssRules[j].style.length; k++){
let name = styleSheets[i].cssRules[j].style[k];
// test name for css variable signiture and uniquenessif(name.startsWith('--') && cssVars.indexOf(name) == -1){
cssVars.push(name);
}
}
} catch (error) {}
}
} catch (error) {}
}
return cssVars;
}
functiongetElementCSSVariables (allCSSVars, element = document.body, pseudo){
var elStyles = window.getComputedStyle(element, pseudo);
var cssVars = {};
for(var i = 0; i < allCSSVars.length; i++){
let key = allCSSVars[i];
let value = elStyles.getPropertyValue(key)
if(value){cssVars[key] = value;}
}
return cssVars;
}
var cssVars = getAllCSSVariableNames();
console.log(':root variables', getElementCSSVariables(cssVars, document.documentElement));
Solution 3:
You can declare an associative array with the keys as the node property with their values, then use a function to set your theme:
var primaryColor = document.documentElement.style.getPropertyValue('--primaryColor');
var secondaryColor = document.documentElement.style.getPropertyValue('--secondaryColor');
var errorColor = document.documentElement.style.getPropertyValue('--errorColor');
var themeColors = {}
themeColors["--primaryColor"] = primaryColor;
themeColors["--secondaryColor"] = secondaryColor;
themeColors["--errorColor"] = errorColor;
functionsetTheme(theme) {
for (key in theme) {
let color = theme[key];
document.documentElement.style.setProperty(key, color);
}
}
A working example I used with Atom and Bootstrap:
var backgroundColor = document.documentElement.style.getPropertyValue('--blue');
backgroundColor = "#dc3545";
functionsetTheme(theme) {
for (key in theme) {
let color = theme[key];
document.documentElement.style.setProperty(key, color);
}
}
var theme = {}
theme["--blue"] = backgroundColor;
setTheme(theme);
>>Edit<<
Nadeem clarified the question a bit better with a comment below, unfortunately however I've learned that :root
can be accessed with get Window.getComputedStyle()
however this doesn't return CSS Variable declarations.
A hack around this is just to read the css file, parse it for variables and stuff them into an associative array, but even this assumes you know where to get that css file...
//an associative array that will hold our valuesvar cssVars = {};
var request = newXMLHttpRequest();
request.open('GET', './css/style.css', true);
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
//Get all CSS Variables in the documentvar matches = request.responseText.match(/(--)\w.+;/gi);
//Get all CSS Variables in the documentfor(let match in matches) {
var property = matches[match];
//split the Variable name from its valuelet splitprop = property.split(":")
//turn the value into a stringlet value = splitprop[1].toString()
cssVars[splitprop[0]] = value.slice(0, -1); //remove ;
}
// console.log(cssVars);// > Object {--primaryColor: "aliceblue", --secondaryColor: "blue", --errorColor: "#cc2511"}// console.log(Object.keys(cssVars));// > ["--primaryColor", "--secondaryColor", "--errorColor" ]setTheme(cssVars)
} else {
// We reached our target server, but it returned an error
}
};
request.onerror = function() {
console.log("There was a connection error");
};
request.send();
functionsetTheme(theme) {
var keys = Object.keys(theme)
for (key in keys) {
let prop = keys[key]
let color = theme[keys[key]];
console.log(prop, color);
// --primaryColor aliceblue etc...
}
}
Solution 4:
If you know all your variable will be placed inside the :root
and it's the first declaration in your first CSS file, you can try something like this and you will get all the variable inside an Object:
var declaration = document.styleSheets[0].cssRules[0];
var allVar = declaration.style.cssText.split(";");
var result = {}
for (var i = 0; i < allVar.length; i++) {
var a = allVar[i].split(':');
if (a[0] !== "")
result[a[0].trim()] = a[1].trim();
}
console.log(result);
var keys = Object.keys(result);
console.log(keys);
//we change the first variabledocument.documentElement.style.setProperty(keys[0], 'green');
//we change the variable --secondary-colordocument.documentElement.style.setProperty(keys[keys.indexOf("--secondary-color")], 'red');
:root {
--primary-color: aliceblue;
--secondary-color: blue;
--error-color: #cc2511
}
p {
font-size: 25px;
color: var(--primary-color);
border:1px solid var(--secondary-color)
}
<p>Some text</p>
Solution 5:
Here is another in typescript, where I continued work that RLoniello mentioned. It also outputs it as a JS object, that is converts --font-family: "Verdana" to fontFamily: "Verdana".
constCssKeyToJsKey = (key: string) =>
key.replace('--', '').replace(/-./g, (x) => x.toUpperCase()[1]);
constgetAllCSSVariableNames = (styleSheets: StyleSheetList = document.styleSheets) => {
const cssVars = [];
Array.from(styleSheets).forEach((styleSheet) => {
Array.from(styleSheet.cssRules).forEach((rule) => {
if (!rule || !rule['style']) {
return;
}
Array.from(rule['style']).forEach((style: string) => {
if (style.startsWith('--') && cssVars.indexOf(style) == -1) {
cssVars.push(style);
}
});
});
});
return cssVars;
};
constgetElementCSSVariables = (
allCSSVars: Array<string>,
element: HTMLElement = document.body,
pseudo: string | undefined = '') => {
const elStyles = window.getComputedStyle(element, pseudo);
const cssVars = {};
allCSSVars.forEach((key) => {
const value = elStyles.getPropertyValue(key);
if (value) {
cssVars[CssKeyToJsKey(key)] = value;
}
});
return cssVars;
};
exportconst getAllCSSVariables = (): Record<string, string> => {
const cssVars = getAllCSSVariableNames();
returngetElementCSSVariables(cssVars, document.documentElement);
};
Post a Comment for "Get All Css Root Variables In Array Using Javascript And Change The Values"