如何通过JavaScript添加/更新作用域CSS变量



是否有本地API可以更新样式表中预定义的特定CSS类(甚至任何其他复杂CSS选择器(下的CSS变量?这个问题不仅可以推广到CSS变量,还可以推广到其他CSS属性,即是否可以在不针对特定HTML元素的情况下,而是通过针对类定义本身来更新类特定的CSS属性。

请在下面找到演示示例场景的代码片段。您还可以在代码中找到关于我认为正在发生的事情/我在特定行中所做的事情的注释。

var toggle = true;
function changeColor() {
document.documentElement.style.setProperty('--bg-color', toggle ? 'green' : 'red');
// this works for the "outer" div since there we receive global value(value defined in :root) of --bg-color
toggle = !toggle;
// here I want to also change the scoped value of --bg-color for "inner-primary" and "inner-secondary"
// currently I can do this by doing:
document.querySelectorAll('.inner-primary').forEach(ele => ele.style.setProperty('--bg-color', toggle ? 'blue' : 'yellow'))
document.querySelectorAll('.inner-secondary').forEach(ele => ele.style.setProperty('--bg-color', toggle ? 'yellow' : 'blue' ))
// another way I can see is: we dynamically insert a style tag, but this feels very awkward and can quickly get out of hand on multiple iterations
}
:root {
--bg-color: red;
}
body {
margin: 0;
}
.outer {
width: 100vw;
height: auto;
min-height: 100vh;
text-align: center;
background-color: var(--bg-color); /* receives value from :root */
}
.inner-primary,
.inner-secondary {
width: 100px;
height: 100px;
/* received scoped value from .inner-primary or .inner-secondary defined below*/
background-color: var(--bg-color);
border: 1px solid black;
margin: auto;
margin-bottom: 10px;
}
.inner-secondary {
--bg-color: yellow;
}
.inner-primary {
--bg-color: blue;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Testing</title>
</head>
<body>
<div class="outer">
<div class="inner-primary"></div>
<div class="inner-secondary"></div>
<div class="inner-primary"></div>
<div class="inner-secondary"></div>
<button onclick="changeColor()">Change Color</button>
</body>
</html>

请尝试运行此程序以获得预期效果的完整概念。您可以单击";改变颜色";按钮,以查看实际效果。

为了获得CSS变量-bg color对类内部主内部辅助的预期覆盖,我必须将querySelectorAll与所需的CSS选择器(在本例中仅为类名(一起使用,并为找到的每个单独元素迭代设置CSS变量。

根据浏览器读取CSS的本质,另一种解决方案是在DOM中动态插入样式元素标记,并更新所需的CSS变量,范围在所需的类名(或任何其他所需的选择器(下。。但是,如果我们不实现一些系统来重用相同的样式标签,并且在每次切换期间不插入新的样式标签的话,这会让人感到尴尬,并且很快就会失控。

还有别的办法吗?任何本机API都可以解决此问题,而无需访问单个元素或动态插入样式标记。。?

根据A Haworth的建议,并参考Javascript中类的CSS?我可以更新changeColor函数来使用CSSTyleSheet(MDN链接(。请找到下面更新的函数,它使用这个API:

var toggle = true;
function changeColor() {
document.documentElement.style.setProperty('--bg-color', toggle ? 'green' : 'red');
// solution using document stylesheets
const styleSheet = document.styleSheets[0]
const cssRules = Array.from(styleSheet.cssRules);
const primaryClassIndex = cssRules.findIndex(cssRule => cssRule.selectorText === '.inner-primary');
const secondaryClassIndex = cssRules.findIndex(cssRule => cssRule.selectorText === '.inner-secondary');
//update primary:
styleSheet.deleteRule(primaryClassIndex);
styleSheet.insertRule(`.inner-primary {--bg-color: ${toggle ? 'yellow' : 'blue'};}`, primaryClassIndex)
//update secondary:
styleSheet.deleteRule(secondaryClassIndex);
styleSheet.insertRule(`.inner-secondary {--bg-color: ${toggle ? 'blue' : 'yellow'};}`, secondaryClassIndex)

//toggle
toggle = !toggle;
}

这仍然是一个问题,因为我们似乎只能覆盖特定选择器的整个cssRule(可能还包括其他CSS属性(,而不仅仅是一个必需的属性。但这可能比更新每个单独的元素样式或插入问题中提到的样式标签要好。

可以在=>https://codepen.io/yadus/pen/mdWZmXX

最新更新