使用javascript获取数组中的所有css根变量并更改值
Posted
技术标签:
【中文标题】使用javascript获取数组中的所有css根变量并更改值【英文标题】:Get all css root variables in array using javascript and change the values 【发布时间】:2018-07-23 10:30:05 【问题描述】:我在我的项目中使用 css 根变量来随时动态更改所有元素的颜色。
我的 CSS 看起来像
:root
--primaryColor:aliceblue;
--secondaryColor:blue;
--errorColor:#cc2511;
在css中使用
.contentCss
background-color: var(--primaryColor);
我可以如下访问javascript中的变量以动态更改值
document.documentElement.style.setProperty('--primaryColor', 'green');
它工作正常。我想获取数组中的所有变量,并据此动态更改每个变量的值。
【问题讨论】:
【参考方案1】:这是另一个打字稿,我继续 RLoniello 提到的工作。它还将其输出为 JS 对象,即将 --font-family: "Verdana" 转换为 fontFamily: "Verdana"。
const CssKeyToJsKey = (key: string) =>
key.replace('--', '').replace(/-./g, (x) => x.toUpperCase()[1]);
const getAllCSSVariableNames = (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;
;
const getElementCSSVariables = (
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;
;
export const getAllCSSVariables = (): Record<string, string> =>
const cssVars = getAllCSSVariableNames();
return getElementCSSVariables(cssVars, document.documentElement);
;
【讨论】:
【参考方案2】:此脚本将返回所有样式表中的根变量数组,由域提供。由于 CORS 策略,无法访问域外样式表。
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),
[]
)
]),
[]
);
注意:较低顺序样式表中的root:
规则将覆盖父root
规则。
【讨论】:
【参考方案3】:我今天需要一个类似的解决方案。这是quick one on codepen。
// could pass in an array of specific stylesheets for optimization
function getAllCSSVariableNames(styleSheets = document.styleSheets)
var cssVars = [];
// loop each stylesheet
for(var i = 0; i < styleSheets.length; i++)
// loop stylesheet's cssRules
try // try/catch used because 'hasOwnProperty' doesn't work
for( 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 uniqueness
if(name.startsWith('--') && cssVars.indexOf(name) == -1)
cssVars.push(name);
catch (error)
catch (error)
return cssVars;
function getElementCSSVariables (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));
【讨论】:
【参考方案4】:如果您知道您的所有变量都将放在 :root
中,并且这是您的第一个 CSS 文件中的第一个声明,您可以尝试这样的操作,您将在 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 variable
document.documentElement.style.setProperty(keys[0], 'green');
//we change the variable --secondary-color
document.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>
【讨论】:
有趣的解决方案,很干净,我考虑过使用.cssRules[0]
,但我发现只读取了第一个:root
元素。如果您有多个来自不同来源的文件,比如本地和 CDN,则只会读取第一个。
@RLoniello 是的,您可能会注意到我使用了0
索引,如果您按照它们进行操作,您会看到我采用了第一个 CSS 文件和该 CSS 文件中的第一条规则......所以你可以对另一个做同样的事情,你唯一需要知道的是顺序和索引......这是一个小缺点:)但是如果你知道你的 CSS 文件就不会成为问题;)
@RLoniello 使用console.log 和document.styleSheets
看看里面有什么,你就会明白;)
是的,我明白了 :) 请注意 CDN 样式表的加载顺序。 :P
@RLoniello 是的,如果你很容易得到订单......但如果不是你可以使代码更复杂,你可以循环遍历所有样式以获取变量..所以几乎相同的事情我已经完成了,但是所有的样式.. 你只需要添加一个if else
来检查样式是否是一个变量(它应该以--
开头)【参考方案5】:
您可以声明一个带有键的关联数组作为节点属性及其值,然后使用函数来设置您的主题:
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;
function setTheme(theme)
for (key in theme)
let color = theme[key];
document.documentElement.style.setProperty(key, color);
我使用 Atom 和 Bootstrap 的一个工作示例:
var backgroundColor = document.documentElement.style.getPropertyValue('--blue');
backgroundColor = "#dc3545";
function setTheme(theme)
for (key in theme)
let color = theme[key];
document.documentElement.style.setProperty(key, color);
var theme =
theme["--blue"] = backgroundColor;
setTheme(theme);
>>编辑
Nadeem 在下面的评论中更好地澄清了这个问题,但不幸的是,我了解到 :root
可以使用 get Window.getComputedStyle()
访问,但这不会返回 CSS 变量声明。
解决这个问题的方法是读取 css 文件,解析变量并将它们填充到关联数组中,但即使这样也假设您知道从哪里获取 css 文件...
//an associative array that will hold our values
var cssVars = ;
var request = new XMLHttpRequest();
request.open('GET', './css/style.css', true);
request.onload = function()
if (request.status >= 200 && request.status < 400)
//Get all CSS Variables in the document
var matches = request.responseText.match(/(--)\w.+;/gi);
//Get all CSS Variables in the document
for(let match in matches)
var property = matches[match];
//split the Variable name from its value
let splitprop = property.split(":")
//turn the value into a string
let 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();
function setTheme(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...
【讨论】:
假设我在 css 中有 200 个变量,所以我必须写这一行 var primaryColor = document.documentElement.style.getPropertyValue('--primaryColor'); 200 次。我想要动态的。以上是关于使用javascript获取数组中的所有css根变量并更改值的主要内容,如果未能解决你的问题,请参考以下文章